home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume12 / cake / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-10-14  |  56.8 KB

  1. Subject:  v12i009:  Cake, a make replacement, Part03/09
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Zoltan Somogyi <zs@munnari.oz>
  7. Posting-number: Volume 12, Issue 9
  8. Archive-name: cake/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create:
  15. #    list.c
  16. #    main.c
  17. #    make.c
  18. #    mem.c
  19. #    pat.c
  20. #    print.c
  21. #    proc.c
  22. #    sym.c
  23. #    sys.c
  24. #    table.c
  25. #    test.c
  26. #    trail.c
  27. # This archive created: Wed Oct 14 21:10:02 1987
  28. export PATH; PATH=/bin:/usr/bin:$PATH
  29. echo shar: "extracting 'list.c'" '(2669 characters)'
  30. if test -f 'list.c'
  31. then
  32.     echo shar: "will not over-write existing file 'list.c'"
  33. else
  34. sed 's/^X//' << \SHAR_EOF > 'list.c'
  35. X/*
  36. X**    Linked list module.
  37. X*/
  38. X
  39. Xstatic    char
  40. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/list.c,v 1.14 86/07/19 12:23:15 zs Exp $";
  41. X
  42. X#include    "cake.h"
  43. X
  44. X/*
  45. X**    Make an empty list.
  46. X*/
  47. X
  48. XList *
  49. Xmakelist0()
  50. X{
  51. X    reg    List    *list;
  52. X
  53. X    list = make(List);
  54. X    ldata(list) = (Cast) 0;
  55. X    next(list)  = list;
  56. X    prev(list)  = list;
  57. X    
  58. X    return list;
  59. X}
  60. X
  61. X/*
  62. X**    Make a list with the argument is its only element.
  63. X*/
  64. X
  65. XList *
  66. X_makelist(data)
  67. Xreg    Cast    data;
  68. X{
  69. X    return addhead(makelist0(), data);
  70. X}
  71. X
  72. X/*
  73. X**    Add some data to the head of a list.
  74. X*/
  75. X
  76. XList *
  77. X_addhead(list, data)
  78. Xreg    List    *list;
  79. Xreg    Cast    data;
  80. X{
  81. X    reg    List    *item;
  82. X
  83. X    if (list == NULL)
  84. X        list = makelist0();
  85. X
  86. X    item = make(List);
  87. X    ldata(item) = data;
  88. X    ldata(list) = (Cast) ((int) ldata(list) + 1);
  89. X
  90. X    /* item's pointers    */
  91. X    next(item) = next(list);
  92. X    prev(item) = list;
  93. X    /* neighbours' pointers    */
  94. X    next(prev(item)) = item;
  95. X    prev(next(item)) = item;
  96. X
  97. X    return list;
  98. X}
  99. X
  100. X/*
  101. X**    Add some data to the tail of a list.
  102. X*/
  103. X
  104. XList *
  105. X_addtail(list, data)
  106. Xreg    List    *list;
  107. Xreg    Cast    data;
  108. X{
  109. X    reg    List    *item;
  110. X
  111. X    if (list == NULL)
  112. X        list = makelist0();
  113. X
  114. X    item = make(List);
  115. X    ldata(item) = data;
  116. X    ldata(list) = (Cast) ((int) ldata(list) + 1);
  117. X
  118. X    /* item's pointers    */
  119. X    next(item) = list;
  120. X    prev(item) = prev(list);
  121. X    /* neighbours' pointers    */
  122. X    next(prev(item)) = item;
  123. X    prev(next(item)) = item;
  124. X
  125. X    return list;
  126. X}
  127. X
  128. X/*
  129. X**    Destructively append list2 to list1. Since the header of
  130. X**    list2 is not meaningful after the operation, it is freed.
  131. X*/
  132. X
  133. XList *
  134. Xaddlist(list1, list2)
  135. Xreg    List    *list1;
  136. Xreg    List    *list2;
  137. X{
  138. X    if (list1 == NULL)
  139. X        list1 = makelist0();
  140. X
  141. X    if (list2 == NULL)
  142. X        list2 = makelist0();
  143. X
  144. X    if (length(list2) > 0)
  145. X    {
  146. X        if (length(list1) == 0)
  147. X        {
  148. X            ldata(list1) = ldata(list2);
  149. X            /* pointers from header    */
  150. X            next(list1)  = next(list2);
  151. X            prev(list1)  = prev(list2);
  152. X            /* pointers to header    */
  153. X            prev(next(list1)) = list1;
  154. X            next(prev(list1)) = list1;
  155. X        }
  156. X        else
  157. X        {
  158. X            ldata(list1) = (Cast) ((int) ldata(list1) + (int) ldata(list2));
  159. X            /* end of list 1 to start of list 2    */
  160. X            next(prev(list1)) = next(list2);
  161. X            prev(next(list2)) = prev(list1);
  162. X            /* end of list 2 to start of list 1    */
  163. X            next(prev(list2)) = list1;
  164. X            prev(list1) = prev(list2);
  165. X        }
  166. X    }
  167. X
  168. X    oldmem((Cast) list2);
  169. X    return list1;
  170. X}
  171. X
  172. X/*
  173. X**    Return the length of a given list.
  174. X*/
  175. X
  176. Xint
  177. Xlength(list)
  178. Xreg    List    *list;
  179. X{
  180. X    if (list == NULL)
  181. X        return 0;
  182. X
  183. X    return (int) ldata(list);
  184. X}
  185. X
  186. X/*
  187. X**    Delete an item from its linked list, and free the node.
  188. X*/
  189. X
  190. Xdelete(list, item)
  191. Xreg    List    *list;
  192. Xreg    List    *item;
  193. X{
  194. X    if (list == NULL)
  195. X        return;
  196. X
  197. X    if (item == NULL)
  198. X        return;
  199. X
  200. X    ldata(list) = (Cast) ((int) ldata(list) - 1);
  201. X    next(prev(item)) = next(item);
  202. X    prev(next(item)) = prev(item);
  203. X
  204. X    oldmem((Cast) item);
  205. X}
  206. SHAR_EOF
  207. if test 2669 -ne "`wc -c < 'list.c'`"
  208. then
  209.     echo shar: "error transmitting 'list.c'" '(should have been 2669 characters)'
  210. fi
  211. fi
  212. echo shar: "extracting 'main.c'" '(9780 characters)'
  213. if test -f 'main.c'
  214. then
  215.     echo shar: "will not over-write existing file 'main.c'"
  216. else
  217. sed 's/^X//' << \SHAR_EOF > 'main.c'
  218. X/*
  219. X**    Cake main file.
  220. X*/
  221. X
  222. Xstatic    char
  223. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/main.c,v 1.15 87/10/05 20:14:53 zs Exp $";
  224. X
  225. X#include    "cake.h"
  226. X#include    <pwd.h>
  227. X#include    <signal.h>
  228. X#include    <sys/stat.h>
  229. X
  230. Xtypedef    struct    passwd    Pwent;
  231. Xtypedef    struct    stat    Stat;
  232. X
  233. Xint    Gflag = FALSE;
  234. Xint    Lflag = FALSE;
  235. Xint    Rflag = FALSE;
  236. Xint    Xflag = FALSE;
  237. Xint    Zflag = FALSE;
  238. Xint    bflag = FALSE;
  239. Xint    cflag = FALSE;
  240. Xint    dflag = FALSE;
  241. Xint    gflag = FALSE;
  242. Xint    iflag = FALSE;
  243. Xint    kflag = TRUE;
  244. Xint    nflag = FALSE;
  245. Xint    qflag = FALSE;
  246. Xint    rflag = FALSE;
  247. Xint    sflag = FALSE;
  248. Xint    tflag = FALSE;
  249. Xint    vflag = FALSE;
  250. Xint    wflag = FALSE;
  251. Xint    xflag = FALSE;
  252. Xint    zflag = FALSE;
  253. X
  254. Xchar    *cakefile  = NULL;
  255. Xchar    *shellfile[2] = { SYSTEM_CMD, SCRIPT_CMD };
  256. Xchar    *metachars = METACHARS;
  257. Xint    maxprocs   = 1;
  258. XList    *active_procs;
  259. Xchar    scratchbuf[128];
  260. X
  261. Xint    cakedebug    = FALSE;
  262. Xint    entrydebug    = FALSE;
  263. Xint    patdebug    = FALSE;
  264. Xint    lexdebug    = FALSE;
  265. X
  266. Xchar    cakeflagbuf[MAXSIZE];
  267. Xchar    *cppargv[MAXARGS];
  268. Xint    cppargc = 0;
  269. X
  270. Xmain(argc, argv)
  271. Xint    argc;
  272. Xchar    **argv;
  273. X{
  274. X    extern        cake_abort(), cake_finish();
  275. X    extern    int    parse_args(), process_args();
  276. X    extern    Node    *chase();
  277. X    extern    char    *getenv();
  278. X    extern    char    *dir_setup();
  279. X    extern    Pwent    *getpwuid();
  280. X    extern    int    geteuid();
  281. X    extern    FILE    *cake_popen();
  282. X    extern    FILE    *yyin;
  283. X    extern    int    yydebug;
  284. X    Stat        statbuf;
  285. X    int        envc;
  286. X    char        *envv[MAXARGS];
  287. X    reg    Pwent    *pwent;
  288. X    reg    char    *envstr;
  289. X    reg    int    status;
  290. X    reg    Node    *rootnode;
  291. X
  292. X    signal(SIGINT,  cake_finish);
  293. X    signal(SIGQUIT, cake_finish);
  294. X    signal(SIGILL,  cake_abort);
  295. X    signal(SIGTRAP, cake_abort);
  296. X    signal(SIGIOT,  cake_abort);
  297. X    signal(SIGEMT,  cake_abort);
  298. X    signal(SIGFPE,  cake_abort);
  299. X    signal(SIGBUS,  cake_abort);
  300. X    signal(SIGSEGV, cake_abort);
  301. X    signal(SIGSYS,  cake_abort);
  302. X    signal(SIGPIPE, cake_abort);
  303. X    signal(SIGALRM, cake_abort);
  304. X
  305. X    yydebug = FALSE;
  306. X    active_procs = makelist0();
  307. X
  308. X    if (rindex(argv[0], 'f') != NULL
  309. X    &&  streq(rindex(argv[0], 'f'), "fake"))
  310. X        cakedebug = TRUE;
  311. X
  312. X    init_sym();
  313. X    cppargv[cppargc++] = new_name(CPP);
  314. X    strcpy(cakeflagbuf, "-DCAKEFLAGS=");
  315. X
  316. X    if ((envstr = getenv("CAKE")) != NULL)
  317. X    {
  318. X        envc = parse_args(envstr, envv);
  319. X        process_args(envv, &envc, 0);
  320. X        if (envc > 0)
  321. X            fprintf(stderr, "cake: non-options in environment ignored\n");
  322. X    }
  323. X
  324. X    argv += process_args(argv, &argc, 1);
  325. X
  326. X#ifdef    CAKEDEBUG
  327. X    if (cakedebug || entrydebug || patdebug || lexdebug)
  328. X        setlinebuf(stdout);
  329. X#endif
  330. X
  331. X    if (cakefile == NULL)
  332. X    {
  333. X        if (stat("cakefile", &statbuf) == 0)
  334. X            cakefile = "cakefile";
  335. X        or (stat("Cakefile", &statbuf) == 0)
  336. X            cakefile = "Cakefile";
  337. X        or (stat("recipe", &statbuf) == 0)
  338. X            cakefile = "recipe";
  339. X        or (stat("Recipe", &statbuf) == 0)
  340. X            cakefile = "Recipe";
  341. X        else
  342. X        {
  343. X            fprintf(stderr, "cake: cannot locate a cakefile\n");
  344. X            exit(1);
  345. X        }
  346. X    }
  347. X
  348. X    if (gflag)
  349. X        cakefile = dir_setup(cakefile);
  350. X
  351. X    pwent = getpwuid(geteuid());
  352. X    strcpy(scratchbuf, "-I");
  353. X    strcat(scratchbuf, pwent->pw_dir);
  354. X    strcat(scratchbuf, ULIB);
  355. X    cppargv[cppargc++] = new_name(scratchbuf);
  356. X    strcpy(scratchbuf, "-I");
  357. X    strcat(scratchbuf, SLIB);
  358. X    cppargv[cppargc++] = new_name(scratchbuf);
  359. X    cppargv[cppargc++] = cakeflagbuf;
  360. X    cppargv[cppargc++] = cakefile;
  361. X    cppargv[cppargc]   = NULL;
  362. X
  363. X    if (cakedebug)
  364. X    {
  365. X        reg    int    i;
  366. X
  367. X        for (i = 0; i < cppargc; i++)
  368. X            printf("%s\n", cppargv[i]);
  369. X    }
  370. X
  371. X    if ((yyin = cake_popen(cppargv, "r")) == NULL)
  372. X    {
  373. X        fprintf(stderr, "cake: cannot open cpp filter\n");
  374. X        exit(1);
  375. X    }
  376. X
  377. X    if (Zflag)
  378. X    {
  379. X        reg    int    c;
  380. X
  381. X        while ((c = getc(yyin)) != EOF)
  382. X            putchar(c);
  383. X
  384. X        cake_pclose(yyin);
  385. X        exit(0);
  386. X    }
  387. X
  388. X    yyinit();
  389. X    init_entry();
  390. X    if (yyparse())
  391. X    {
  392. X        fprintf(stderr, "cake: cannot parse %s\n", cakefile);
  393. X        exit(1);
  394. X    }
  395. X
  396. X    shell_setup(shellfile[0], 0);
  397. X    shell_setup(shellfile[1], 1);
  398. X    meta_setup(metachars);
  399. X
  400. X    cake_pclose(yyin);
  401. X    dir_start();
  402. X    prep_entries();
  403. X    final_entry(argc, argv);
  404. X
  405. X    rootnode = chase(CHASEROOT, 0, (Entry *) NULL);
  406. X
  407. X    if (! qflag)
  408. X        execute(rootnode);
  409. X    
  410. X    dir_finish();
  411. X    cleanup();
  412. X#ifdef    STATS_FILE
  413. X    statistics();
  414. X#endif
  415. X
  416. X    status = (off_node(rootnode, nf_ERR) && is_ok(rootnode))? 0: 1;
  417. X    cdebug("exit status %d\n", status);
  418. X    exit(status);
  419. X}
  420. X
  421. Xint
  422. Xprocess_args(vector, count, base)
  423. Xreg    char    **vector;
  424. Xreg    int    *count;
  425. Xreg    int    base;
  426. X{
  427. X    reg    int    i, j;
  428. X
  429. X    j = 0;
  430. X    cdebug("process args:");
  431. X    while (*count > base && vector[base][0] == '-')
  432. X    {
  433. X        putflag(base, vector[base]);
  434. X
  435. X        for (i = 1; vector[base][i] != '\0'; i++)
  436. X        {
  437. X            switch (vector[base][i])
  438. X            {
  439. X
  440. X#ifdef    CAKEDEBUG
  441. X        when 'C':    cdebug(" -C");
  442. X                cakedebug  = ! cakedebug;
  443. X        
  444. X        when 'E':    cdebug(" -E");
  445. X                entrydebug = ! entrydebug;
  446. X        
  447. X        when 'P':    cdebug(" -P");
  448. X                patdebug   = ! patdebug;
  449. X        
  450. X        when 'W':    cdebug(" -W");
  451. X                lexdebug   = TRUE;
  452. X        
  453. X        when 'Y':    cdebug(" -Y");
  454. X                yydebug    = TRUE;
  455. X#endif
  456. X        when 'G':    cdebug(" -G");
  457. X                Gflag = TRUE;
  458. X        
  459. X        when 'L':    cdebug(" -L");
  460. X                Lflag = TRUE;
  461. X        
  462. X        when 'R':    cdebug(" -R");
  463. X                Rflag = TRUE;
  464. X        
  465. X        when 'X':    cdebug(" -X");
  466. X                Xflag = TRUE;
  467. X        
  468. X        when 'Z':    cdebug(" -Z");
  469. X                Zflag = TRUE;
  470. X        
  471. X        when 'a':    cdebug(" -a");
  472. X                kflag = FALSE;
  473. X        
  474. X        when 'b':    cdebug(" -b");
  475. X                bflag = TRUE;
  476. X        
  477. X        when 'c':    cdebug(" -c");
  478. X                cflag = TRUE;
  479. X        
  480. X        when 'd':    cdebug(" -d");
  481. X                dflag = TRUE;
  482. X        
  483. X        when 'g':    cdebug(" -g");
  484. X                gflag = TRUE;
  485. X        
  486. X        when 'i':    cdebug(" -i");
  487. X                iflag = TRUE;
  488. X        
  489. X        when 'k':    cdebug(" -k");
  490. X                kflag = TRUE;
  491. X        
  492. X        when 'n':    cdebug(" -n");
  493. X                nflag = TRUE;
  494. X                tflag = FALSE;
  495. X                qflag = FALSE;
  496. X        
  497. X        when 'q':    cdebug(" -q");
  498. X                qflag = TRUE;
  499. X                nflag = FALSE;
  500. X                tflag = FALSE;
  501. X        
  502. X        when 'r':    cdebug(" -r");
  503. X                rflag = TRUE;
  504. X        
  505. X        when 's':    cdebug(" -s");
  506. X                sflag = TRUE;
  507. X        
  508. X        when 't':    cdebug(" -t");
  509. X                tflag = TRUE;
  510. X                nflag = FALSE;
  511. X                qflag = FALSE;
  512. X        
  513. X        when 'v':    cdebug(" -v");
  514. X                vflag = TRUE;
  515. X        
  516. X        when 'w':    cdebug(" -w");
  517. X                wflag = TRUE;
  518. X        
  519. X        when 'x':    cdebug(" -x");
  520. X                xflag = TRUE;
  521. X        
  522. X        when 'z':    cdebug(" -z");
  523. X                zflag = TRUE;
  524. X        
  525. X        when 'D':
  526. X        case 'I':
  527. X        case 'U':    if (i != 1)
  528. X                    usage();
  529. X
  530. X                cdebug(" %s", vector[base]);
  531. X                cppargv[cppargc++] = new_name(vector[base]);
  532. X                goto nextword;
  533. X        
  534. X        when 'N':    putflag(base, vector[base+1]);
  535. X                sscanf(vector[base+1], "%d", &maxprocs);
  536. X                if (vector[base][i+1] != '\0')
  537. X                    usage();
  538. X
  539. X                cdebug(" -N %d", maxprocs);
  540. X                (*count)--;
  541. X                vector++, j++;
  542. X                goto nextword;
  543. X        
  544. X        when 'S':    putflag(base, vector[base+1]);
  545. X                if (vector[base][i+1] == '1')
  546. X                    shellfile[0] = new_name(vector[base+1]);
  547. X                or (vector[base][i+1] == '2')
  548. X                    shellfile[1] = new_name(vector[base+1]);
  549. X                else
  550. X                    usage();
  551. X
  552. X                if (vector[base][i+2] != '\0')
  553. X                    usage();
  554. X
  555. X                cdebug(" -S%c %s", vector[base][i+1], vector[base+1]);
  556. X                (*count)--;
  557. X                vector++, j++;
  558. X                goto nextword;
  559. X        
  560. X        when 'T':    putflag(base, vector[base+1]);
  561. X                metachars = new_name(vector[base+1]);
  562. X                if (vector[base][i+1] != '\0')
  563. X                    usage();
  564. X
  565. X                cdebug(" -T %s", metachars);
  566. X                (*count)--;
  567. X                vector++, j++;
  568. X                goto nextword;
  569. X        
  570. X        when 'f':    putflag(base, vector[base+1]);
  571. X                cakefile = new_name(vector[base+1]);
  572. X                if (vector[base][i+1] != '\0')
  573. X                    usage();
  574. X
  575. X                cdebug(" -f %s", cakefile);
  576. X                (*count)--;
  577. X                vector++, j++;
  578. X                goto nextword;
  579. X
  580. X        otherwise:    usage();
  581. X            }
  582. X        }
  583. X
  584. Xnextword:
  585. X        (*count)--;
  586. X        vector++, j++;
  587. X    }
  588. X
  589. X    cdebug(" \n%return %d\n", j);
  590. X    return j;
  591. X}
  592. X
  593. X/*
  594. X**    Put a flag into the CAKEFLAGS definition.
  595. X*/
  596. X
  597. Xputflag(base, flag)
  598. Xreg    int    base;
  599. Xreg    char    *flag;
  600. X{
  601. X    if (base == 1)
  602. X    {
  603. X        strcat(cakeflagbuf, " ");
  604. X        strcat(cakeflagbuf, flag);
  605. X        if (strlen(cakeflagbuf) >= MAXSIZE)
  606. X        {
  607. X            fprintf(stderr, "cake: CAKEFLAGS too long\n");
  608. X            exit(1);
  609. X        }
  610. X    }
  611. X}
  612. X
  613. X/*
  614. X**    Tell the unfortunate user how to use cake.
  615. X*/
  616. X
  617. Xusage()
  618. X{
  619. X    fprintf(stderr, "Usage: cake [-abcdgiknqrstvwxzGLRXZ] [-ffile]\n");
  620. X    fprintf(stderr, "       [-Ddefn] [-Idir] [-Uname] [-S shell] [-T metachars] [file ...]\n");
  621. X    exit(1);
  622. X}
  623. X
  624. Xexit_cake(needtrail)
  625. Xreg    int    needtrail;
  626. X{
  627. X    if (cakedebug && needtrail)
  628. X        get_trail(stdout);
  629. X    else
  630. X        dir_finish();
  631. X
  632. X    exit(1);
  633. X}
  634. X
  635. X/*
  636. X**    Handle bus errors and segmentation violations.
  637. X*/
  638. X
  639. Xcake_abort()
  640. X{
  641. X
  642. X    signal(SIGINT,  SIG_IGN);
  643. X    signal(SIGQUIT, SIG_IGN);
  644. X
  645. X    printf("Abort on signal\n");
  646. X    if (cakedebug)
  647. X        get_trail(stdout);
  648. X
  649. X    signal(SIGQUIT, SIG_DFL);
  650. X    kill(getpid(), SIGQUIT);
  651. X}
  652. X
  653. X/*
  654. X**    Handle user interrupts.
  655. X*/
  656. X
  657. Xcake_finish()
  658. X{
  659. X    reg    List    *ptr;
  660. X    reg    Proc    *proc;
  661. X
  662. X    signal(SIGINT,  SIG_IGN);
  663. X    signal(SIGQUIT, SIG_IGN);
  664. X
  665. X    printf("*** Interrupt\n");
  666. X    fflush(stdout);
  667. X    for_list (ptr, active_procs)
  668. X    {
  669. X        proc = (Proc *) ldata(ptr);
  670. X        if (proc->pr_node != NULL)
  671. X            cake_error(proc->pr_node);
  672. X    }
  673. X
  674. X    exit_cake(FALSE);
  675. X}
  676. X
  677. X#ifdef    STATS_FILE
  678. X#ifdef    ATT
  679. X#include    <sys/times.h>
  680. X
  681. Xtypedef    struct    tms    Tms;
  682. X#else
  683. X#include    <sys/time.h>
  684. X#include    <sys/resource.h>
  685. X
  686. Xtypedef    struct    rusage    Rusage;
  687. X#endif
  688. X
  689. Xstatistics()
  690. X{
  691. X    extern    char    *getlogin();
  692. X    extern        getpw();
  693. X    extern    int    out_tried, out_found;
  694. X    extern    int    stat_tried, stat_found;
  695. X    FILE        *sfp;
  696. X
  697. X    if ((sfp = fopen(STATS_FILE, "a")) != NULL)
  698. X    {
  699. X#ifdef    ATT
  700. X        Tms    tbuf;
  701. X#else
  702. X        Rusage    s, c;
  703. X#endif
  704. X        long    su, ss, cu, cs;
  705. X        char    *usr;
  706. X
  707. X        if ((usr = getlogin()) == NULL)
  708. X        {
  709. X            char    buf[256];
  710. X            char    *usr_end;
  711. X
  712. X            if (getpw(getuid(), buf) != 0)
  713. X                usr = "NULL";
  714. X            else
  715. X            {
  716. X                usr = buf;
  717. X                if ((usr_end = index(usr, ':')) != NULL)
  718. X                    *usr_end = '\0';
  719. X                else
  720. X                    usr = "NULL";
  721. X            }
  722. X
  723. X            usr = new_name(usr);
  724. X        }
  725. X
  726. X#ifdef    ATT
  727. X        if (times(&tbuf) == -1)
  728. X        {
  729. X            fclose(sfp);
  730. X            return;
  731. X        }
  732. X
  733. X        su = tbuf.tms_utime*100/TIMERES;
  734. X        ss = tbuf.tms_stime*100/TIMERES;
  735. X        cu = tbuf.tms_cutime*100/TIMERES;
  736. X        cs = tbuf.tms_cstime*100/TIMERES;
  737. X#else
  738. X        getrusage(RUSAGE_SELF,     &s);
  739. X        getrusage(RUSAGE_CHILDREN, &c);
  740. X
  741. X        su = s.ru_utime.tv_sec*100 + s.ru_utime.tv_usec/10000;
  742. X        ss = s.ru_stime.tv_sec*100 + s.ru_stime.tv_usec/10000;
  743. X        cu = c.ru_utime.tv_sec*100 + c.ru_utime.tv_usec/10000;
  744. X        cs = c.ru_stime.tv_sec*100 + c.ru_stime.tv_usec/10000;
  745. X#endif
  746. X        fprintf(sfp, "%s %ld %ld %ld %ld ", usr, su, ss, cu, cs);
  747. X        fprintf(sfp, "%d %d %d %d %d\n", sbrk(0),
  748. X            out_tried, out_found, stat_tried, stat_found);
  749. X
  750. X        fclose(sfp);
  751. X    }
  752. X}
  753. X#endif
  754. SHAR_EOF
  755. if test 9780 -ne "`wc -c < 'main.c'`"
  756. then
  757.     echo shar: "error transmitting 'main.c'" '(should have been 9780 characters)'
  758. fi
  759. fi
  760. echo shar: "extracting 'make.c'" '(2967 characters)'
  761. if test -f 'make.c'
  762. then
  763.     echo shar: "will not over-write existing file 'make.c'"
  764. else
  765. sed 's/^X//' << \SHAR_EOF > 'make.c'
  766. X/*
  767. X**    Module to make Cake data structures.
  768. X*/
  769. X
  770. Xstatic    char
  771. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/make.c,v 1.15 87/10/05 20:15:02 zs Exp $";
  772. X
  773. X#include    "cake.h"
  774. X
  775. XNode *
  776. Xmake_node(name)
  777. Xreg    char    *name;
  778. X{
  779. X    reg    Node    *node;
  780. X
  781. X    node = make(Node);
  782. X    node->n_name    = name;
  783. X
  784. X    if (name == NULL)
  785. X        return node;
  786. X
  787. X    node->n_kind = n_NOWAY;        /* not yet */
  788. X    node->n_flag = 0;
  789. X    node->n_old  = makelist0();
  790. X    node->n_when = NULL;
  791. X    node->n_act  = NULL;
  792. X    node->n_new  = makelist(node);
  793. X#if 0    /* N must be 1 for the time being */
  794. X    node->n_pid  = 0;
  795. X    node->n_file = NULL;
  796. X#endif
  797. X    node_stat(node);
  798. X    node->n_utime   = 0;
  799. X    node->n_stime   = node->n_rtime;
  800. X    node->n_badguys = NULL;
  801. X    node->n_msg     = NULL;
  802. X
  803. X    return node;
  804. X}
  805. X
  806. XEntry *
  807. Xmake_dep(new, old, cond, file, colon)
  808. Xreg    List    *new;                /* of Pat    */
  809. Xreg    List    *old;                /* of Pat    */
  810. Xreg    Test    *cond;
  811. Xreg    char    *file;
  812. Xreg    char    *colon;
  813. X{
  814. X    reg    Entry    *entry;
  815. X
  816. X    entry = make(Entry);
  817. X    entry->e_new  = new;
  818. X    entry->e_old  = old;
  819. X    entry->e_cond = cond;
  820. X    entry->e_file = file;
  821. X    entry->e_dblc = streq(colon, "::");
  822. X    entry->e_when = makelist0();
  823. X
  824. X    return entry;
  825. X}
  826. X
  827. XTest *
  828. Xmake_test_mm(name)
  829. Xreg    Pat    *name;
  830. X{
  831. X    reg    Test    *test;
  832. X
  833. X    test = make(Test);
  834. X    test->t_kind = t_MATCH;
  835. X    test->t_pat  = name;
  836. X    test->t_list = makelist0();
  837. X
  838. X    return test;
  839. X}
  840. X
  841. XTest *
  842. Xmake_test_m(name, varpat, pattern)
  843. Xreg    Pat    *name;
  844. Xreg    Pat    *varpat;
  845. Xreg    Pat    *pattern;
  846. X{
  847. X    reg    Test    *test;
  848. X
  849. X    test = make(Test);
  850. X    test->t_kind = t_MATCH;
  851. X    test->t_pat  = name;
  852. X    test->t_list = makelist0();
  853. X
  854. X    if (varpat == NULL)
  855. X        addtail(test->t_list, make_pat("-vX", FALSE, 0));
  856. X    else
  857. X        addtail(test->t_list, varpat);    /* no assignment */
  858. X
  859. X    addtail(test->t_list, pattern);        /* no assignment */
  860. X    return test;
  861. X}
  862. X
  863. XTest *
  864. Xmake_test_c(cmd)
  865. Xreg    char    *cmd;
  866. X{
  867. X    reg    Test    *test;
  868. X
  869. X    test = make(Test);
  870. X    test->t_kind = t_CMD;
  871. X    test->t_cmd  = cmd;
  872. X
  873. X    return test;
  874. X}
  875. X
  876. XTest *
  877. Xmake_test_s(tkind, pat)
  878. Xreg    T_kind    tkind;
  879. Xreg    Pat    *pat;
  880. X{
  881. X    reg    Test    *test;
  882. X
  883. X    test = make(Test);
  884. X    test->t_kind = tkind;
  885. X    test->t_pat  = pat;
  886. X
  887. X    return test;
  888. X}
  889. X
  890. XTest *
  891. Xmake_test_l(pat, list)
  892. Xreg    Pat    *pat;
  893. Xreg    List    *list;                /* of Pat    */
  894. X{
  895. X    reg    Test    *test;
  896. X
  897. X    test = make(Test);
  898. X    test->t_kind = t_LIST;
  899. X    test->t_pat  = pat;
  900. X    test->t_list = list;
  901. X
  902. X    return test;
  903. X}
  904. X
  905. XTest *
  906. Xmake_test_b(tkind, left, right)
  907. Xreg    T_kind    tkind;
  908. Xreg    Test    *left;
  909. Xreg    Test    *right;
  910. X{
  911. X    reg    Test    *test;
  912. X
  913. X    test = make(Test);
  914. X    test->t_kind  = tkind;
  915. X    test->t_left  = left;
  916. X    test->t_right = right;
  917. X
  918. X    return test;
  919. X}
  920. X
  921. XTest *
  922. Xmake_test_u(tkind, left)
  923. Xreg    T_kind    tkind;
  924. Xreg    Test    *left;
  925. X{
  926. X    reg    Test    *test;
  927. X
  928. X    test = make(Test);
  929. X    test->t_kind  = tkind;
  930. X    test->t_left  = left;
  931. X    test->t_right = (Test *) NULL;
  932. X
  933. X    return test;
  934. X}
  935. X
  936. XPat *
  937. Xmake_pat(text, iscmd, flags)
  938. Xreg    char    *text;
  939. Xreg    bool    iscmd;
  940. Xreg    int    flags;
  941. X{
  942. X    reg    Pat    *pat;
  943. X
  944. X    pat = make(Pat);
  945. X    pat->p_str  = text;
  946. X    pat->p_cmd  = iscmd;
  947. X    pat->p_flag = flags;
  948. X
  949. X    checkpatlen(text);
  950. X    return pat;
  951. X}
  952. X
  953. XAct *
  954. Xmake_act(str, flag)
  955. Xreg    char    *str;
  956. Xreg    int    flag;
  957. X{
  958. X    reg    Act    *act;
  959. X
  960. X    act = make(Act);
  961. X    act->a_str  = str;
  962. X    act->a_flag = flag;
  963. X
  964. X    return act;
  965. X}
  966. SHAR_EOF
  967. if test 2967 -ne "`wc -c < 'make.c'`"
  968. then
  969.     echo shar: "error transmitting 'make.c'" '(should have been 2967 characters)'
  970. fi
  971. fi
  972. echo shar: "extracting 'mem.c'" '(822 characters)'
  973. if test -f 'mem.c'
  974. then
  975.     echo shar: "will not over-write existing file 'mem.c'"
  976. else
  977. sed 's/^X//' << \SHAR_EOF > 'mem.c'
  978. X/*
  979. X**    Memory management module.
  980. X*/
  981. X
  982. Xstatic    char
  983. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/mem.c,v 1.15 87/10/05 20:15:10 zs Exp $";
  984. X
  985. X#include    "cake.h"
  986. X
  987. X/*
  988. X**    Allocate space if possible. In the future it may record
  989. X**    all pointers returned, so that old can do some checks.
  990. X*/
  991. X
  992. XCast
  993. Xnewmem(size)
  994. Xint    size;
  995. X{
  996. X    reg    char    *space;
  997. X
  998. X    if ((space = malloc((unsigned) size)) == NULL)
  999. X    {
  1000. X        fprintf(stderr, "cake system error: no more malloc\n");
  1001. X        exit_cake(FALSE);
  1002. X    }
  1003. X
  1004. X#ifdef    EXTRACHECK
  1005. X    if (((int) space & 03) != 0)
  1006. X    {
  1007. X        fprintf(stderr, "cake system error: malloc not aligned\n");
  1008. X        exit_cake(FALSE);
  1009. X    }
  1010. X#endif
  1011. X
  1012. X    return (Cast) space;
  1013. X}
  1014. X
  1015. X/*
  1016. X**    Return some storage to the free list. This storage must
  1017. X**    have been obtained from new and malloc.
  1018. X*/
  1019. X
  1020. X/*ARGSUSED*/
  1021. Xoldmem(ptr)
  1022. XCast    ptr;
  1023. X{
  1024. X#ifdef    MEMUSED
  1025. X    free((char *) ptr);
  1026. X#endif
  1027. X}
  1028. SHAR_EOF
  1029. if test 822 -ne "`wc -c < 'mem.c'`"
  1030. then
  1031.     echo shar: "error transmitting 'mem.c'" '(should have been 822 characters)'
  1032. fi
  1033. fi
  1034. echo shar: "extracting 'pat.c'" '(6360 characters)'
  1035. if test -f 'pat.c'
  1036. then
  1037.     echo shar: "will not over-write existing file 'pat.c'"
  1038. else
  1039. sed 's/^X//' << \SHAR_EOF > 'pat.c'
  1040. X/*
  1041. X**    Module to manipulate Cake patterns.
  1042. X*/
  1043. X
  1044. Xstatic    char
  1045. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/pat.c,v 1.15 87/10/05 20:15:15 zs Exp $";
  1046. X
  1047. X#include    "cake.h"
  1048. X#include    <ctype.h>
  1049. X
  1050. X/*
  1051. X**    This function serves as an interface to the rest of the system
  1052. X**    for domatch, looking after its environment.
  1053. X*/
  1054. X
  1055. Xbool
  1056. Xmatch(env, str, pat)
  1057. XEnv        env;
  1058. Xreg    char    *str;
  1059. Xreg    Pat    *pat;
  1060. X{
  1061. X    extern    bool    domatch();
  1062. X    reg    bool    result;
  1063. X    reg    int    i;
  1064. X    reg    char    *s, *p;
  1065. X
  1066. X    if (patdebug)
  1067. X        printf("Match %s vs %s\n", str, pat->p_str);
  1068. X
  1069. X    if (pat->p_cmd)
  1070. X    {
  1071. X        fprintf(stderr, "cake internal error: undereferenced pattern %s in match\n",
  1072. X            pat->p_str);
  1073. X        exit_cake(TRUE);
  1074. X    }
  1075. X
  1076. X    if (streq(str, CHASEROOT))
  1077. X        result = streq(pat->p_str, CHASEROOT);
  1078. X    else
  1079. X    {
  1080. X        result = TRUE; /* assume so for the moment */
  1081. X        p = pat->p_str+strlen(pat->p_str)-1;
  1082. X        if (*p != '%' && !isdigit(*p))    /* not part of a var */
  1083. X        {
  1084. X            s = str+strlen(str)-1;
  1085. X            if (*s != *p)        /* last chars differ */
  1086. X                result = FALSE;
  1087. X        }
  1088. X        
  1089. X        if (result) /* if last-char test inconclusive */
  1090. X        {
  1091. X            for (i = 0; i < MAXVAR; i++)
  1092. X                env[i].v_bound = FALSE;
  1093. X
  1094. X            result = domatch(env, str, pat->p_str);
  1095. X        }
  1096. X    }
  1097. X
  1098. X    if (patdebug)
  1099. X    {
  1100. X        if (result == FALSE)
  1101. X            printf("Match failed\n");
  1102. X        else
  1103. X        {
  1104. X            printf("Match succeeded\n");
  1105. X            for (i = 0; i < MAXVAR; i++)
  1106. X                if (env[i].v_bound)
  1107. X                    printf("X%d: %s\n", i, env[i].v_val);
  1108. X        }
  1109. X    }
  1110. X
  1111. X    return result;
  1112. X}
  1113. X
  1114. X/*
  1115. X**    Match a string against a pattern.
  1116. X**    The pattern is expected to have been dereferenced.
  1117. X**    To handle nondeterminism, a brute force recursion approach
  1118. X**    is taken.
  1119. X*/
  1120. X
  1121. Xbool
  1122. Xdomatch(env, str, patstr)
  1123. XEnv        env;
  1124. Xreg    char    *str;
  1125. Xreg    char    *patstr;
  1126. X{
  1127. X    char        buf[MAXPATSIZE];
  1128. X    reg    char    *follow;
  1129. X    reg    char    *s, *t;
  1130. X    reg    int    varno;
  1131. X    reg    int    i;
  1132. X    reg    bool    more;
  1133. X
  1134. X    put_trail("domatch", "start");
  1135. X    if (patstr[0] == '%')
  1136. X    {
  1137. X        if (isdigit(patstr[1]))
  1138. X        {
  1139. X            varno  = patstr[1] - '0';
  1140. X            follow = patstr + 2;
  1141. X        }
  1142. X        else
  1143. X        {
  1144. X            varno  = NOVAR;
  1145. X            follow = patstr + 1;
  1146. X        }
  1147. X
  1148. X        if (env[varno].v_bound)
  1149. X        {
  1150. X            /* lifetime of buf is local */
  1151. X            strcpy(buf, env[varno].v_val);
  1152. X            strcat(buf, follow);
  1153. X            checkpatlen(buf);
  1154. X            put_trail("domatch", "recurse");
  1155. X            return domatch(env, str, buf);
  1156. X        }
  1157. X
  1158. X        i = 0;
  1159. X        buf[0] = '\0';
  1160. X        env[varno].v_bound = TRUE;
  1161. X        env[varno].v_val = buf;
  1162. X
  1163. X        /* keep invariant: buf = tentative value of var  */
  1164. X        /* the value of a variable may never contain a % */
  1165. X        /* must consider *s == \0, but do not overshoot  */
  1166. X        for (s = str, more = TRUE; more && *s != '%'; s++)
  1167. X        {
  1168. X            if (patdebug)
  1169. X                printf("trying X%d = '%s'\n", varno, buf);
  1170. X
  1171. X            if (domatch(env, s, follow))
  1172. X            {
  1173. X                checkpatlen(buf);
  1174. X                env[varno].v_val = new_name(buf);
  1175. X                /* lifetime of buf is now global */
  1176. X                put_trail("domatch", "finish");
  1177. X                return TRUE;
  1178. X            }
  1179. X
  1180. X            /* maintain invariant */
  1181. X            buf[i++] = *s;
  1182. X            buf[i]   = '\0';
  1183. X
  1184. X            more = (*s != '\0');
  1185. X        }
  1186. X        
  1187. X        /* no luck, match failed */
  1188. X        env[varno].v_bound = FALSE;
  1189. X        put_trail("domatch", "finish");
  1190. X        return FALSE;
  1191. X    }
  1192. X
  1193. X    /* here we have something other than a variable first off */
  1194. X    for (s = str, t = patstr; *t != '\0' && *t != '%'; s++, t++)
  1195. X    {
  1196. X        if (*t == '\\')
  1197. X            t++;    /* the new *t is not checked for % */
  1198. X        
  1199. X        if (*s != *t)
  1200. X        {
  1201. X            put_trail("domatch", "finish");
  1202. X            return FALSE;
  1203. X        }
  1204. X    }
  1205. X
  1206. X    /* see if we have come to the end of the pattern */
  1207. X    if (*t == '\0')
  1208. X    {
  1209. X        put_trail("domatch", "finish");
  1210. X        return *s == '\0';
  1211. X    }
  1212. X    
  1213. X    /* if not, recurse on the next variable */
  1214. X    put_trail("domatch", "recurse");
  1215. X    return domatch(env, s, t);
  1216. X}
  1217. X
  1218. X/*
  1219. X**    Ground the argument string, i.e. replace all occurrences
  1220. X**    of variables in it. It is fatal error for the string to
  1221. X**    contain a variable which has no value.
  1222. X*/
  1223. X
  1224. Xchar *
  1225. Xground(env, str)
  1226. XEnv        env;
  1227. Xreg    char    *str;
  1228. X{
  1229. X    reg    char    *s, *t;
  1230. X    reg    int    i, var;
  1231. X    char        buf[MAXSIZE];
  1232. X
  1233. X    put_trail("ground", "start");
  1234. X    i = 0;
  1235. X    for (s = str; *s != '\0'; s++)
  1236. X    {
  1237. X        if (*s == '%')
  1238. X        {
  1239. X            if (isdigit(s[1]))
  1240. X                var = *++s - '0';
  1241. X            else
  1242. X                var = NOVAR;
  1243. X            
  1244. X            if (! env[var].v_bound)
  1245. X            {
  1246. X                if (var == NOVAR)
  1247. X                    fprintf(stderr, "cake: %s is undefined in %s\n", "%", str);
  1248. X                else
  1249. X                    fprintf(stderr, "cake: %s%1d is undefined in %s\n", "%", var, str);
  1250. X                exit_cake(FALSE);
  1251. X            }
  1252. X
  1253. X            for (t = env[var].v_val; *t != '\0'; t++)
  1254. X                buf[i++] = *t;
  1255. X        }
  1256. X        or (*s == '\\')
  1257. X        {
  1258. X            if (s[1] != '\0')
  1259. X                buf[i++] = *++s;
  1260. X        }
  1261. X        else
  1262. X            buf[i++] = *s;
  1263. X    }
  1264. X
  1265. X    buf[i] = '\0';
  1266. X    if (i >= MAXSIZE)
  1267. X    {
  1268. X        fprintf(stderr, "cake internal error: pattern buffer overflow for %s\n", buf);
  1269. X        exit_cake(FALSE);
  1270. X    }
  1271. X
  1272. X    put_trail("ground", "new_name finish");
  1273. X    return new_name(buf);
  1274. X}
  1275. X
  1276. X/*
  1277. X**    See if the argument contains any variebles.
  1278. X*/
  1279. X
  1280. Xbool
  1281. Xhasvars(str)
  1282. Xreg    char    *str;
  1283. X{
  1284. X    reg    char    *s;
  1285. X
  1286. X    for (s = str; *s != '\0'; s++)
  1287. X    {
  1288. X        if (*s == '%')
  1289. X            return TRUE;
  1290. X        or (*s == '\\')
  1291. X        {
  1292. X            if (s[1] != '\0')
  1293. X                s++;
  1294. X        }
  1295. X    }
  1296. X
  1297. X    return FALSE;
  1298. X}
  1299. X
  1300. X/*
  1301. X**    Dereference the pattern; i.e. if it a command pattern
  1302. X**    replace it with the output of the command. It is the task
  1303. X**    of the caller to break this up if necessary.
  1304. X**    Note that the pattern will never have to be dereferenced again.
  1305. X**
  1306. X**    The second arg says whether the pattern is to be broken after
  1307. X**    dereferencing: this is needed purely for debugging purposes.
  1308. X*/
  1309. X
  1310. Xderef(pat, broken)
  1311. Xreg    Pat    *pat;
  1312. Xreg    bool    broken;
  1313. X{
  1314. X    extern    char    *expand_cmds();
  1315. X
  1316. X    if (! pat->p_cmd)
  1317. X        return;
  1318. X    
  1319. X    pat->p_cmd = FALSE;
  1320. X    pat->p_str = expand_cmds(pat->p_str);
  1321. X
  1322. X    if (! broken)
  1323. X        checkpatlen(pat->p_str);
  1324. X}
  1325. X
  1326. X/*
  1327. X**    Break the given pattern up into a (possibly empty) list
  1328. X**    of smaller patterns at white space positions.
  1329. X*/
  1330. X
  1331. XList *
  1332. Xbreak_pat(pat)
  1333. Xreg    Pat    *pat;
  1334. X{
  1335. X    reg    Pat    *newpat;
  1336. X    reg    List    *list;
  1337. X    reg    char    *s;
  1338. X
  1339. X    put_trail("break_pat", "start");
  1340. X    if (pat->p_cmd)
  1341. X    {
  1342. X        fprintf(stderr, "cake internal error: trying to break command pattern %s\n", pat->p_str);
  1343. X        exit_cake(TRUE);
  1344. X    }
  1345. X
  1346. X    list = makelist0();
  1347. X    s = pat->p_str;
  1348. X    while (*s != '\0')
  1349. X    {
  1350. X        char        buf[MAXSIZE];
  1351. X        reg    int    i;
  1352. X
  1353. X        for (; *s != '\0' && isspace(*s); s++)
  1354. X            ;
  1355. X
  1356. X        i = 0;
  1357. X        for (; *s != '\0' && !isspace(*s); s++)
  1358. X            buf[i++] = *s;
  1359. X        
  1360. X        buf[i] = '\0';
  1361. X        if (i > 0)
  1362. X        {
  1363. X            newpat = make_pat(new_name(buf), FALSE, pat->p_flag);
  1364. X            addtail(list, newpat);    /* no assignment */
  1365. X        }
  1366. X    }
  1367. X
  1368. X    put_trail("break_pat", "finish");
  1369. X    return list;
  1370. X}
  1371. X
  1372. X/*
  1373. X**    Add flags to a list of patterns.
  1374. X*/
  1375. X
  1376. XList *
  1377. Xset_flag(patlist, flags)
  1378. Xreg    List    *patlist;
  1379. Xreg    int    flags;
  1380. X{
  1381. X    reg    List    *ptr;
  1382. X    reg    Pat    *pat;
  1383. X
  1384. X    for_list (ptr, patlist)
  1385. X    {
  1386. X        pat = (Pat *) ldata(ptr);
  1387. X        pat->p_flag |= flags;
  1388. X    }
  1389. X
  1390. X    return patlist;
  1391. X}
  1392. SHAR_EOF
  1393. if test 6360 -ne "`wc -c < 'pat.c'`"
  1394. then
  1395.     echo shar: "error transmitting 'pat.c'" '(should have been 6360 characters)'
  1396. fi
  1397. fi
  1398. echo shar: "extracting 'print.c'" '(4954 characters)'
  1399. if test -f 'print.c'
  1400. then
  1401.     echo shar: "will not over-write existing file 'print.c'"
  1402. else
  1403. sed 's/^X//' << \SHAR_EOF > 'print.c'
  1404. X/*
  1405. X**    Printout routines for Cake data structures.
  1406. X*/
  1407. X
  1408. X#ifdef    CAKEDEBUG
  1409. X
  1410. Xstatic    char
  1411. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/print.c,v 1.15 87/10/05 20:15:33 zs Exp $";
  1412. X
  1413. X#include    "cake.h"
  1414. X
  1415. Xchar *
  1416. Xstr_pflag(flag)
  1417. Xreg    int    flag;
  1418. X{
  1419. X    char        buf[256];
  1420. X
  1421. X    strcpy(buf, "[");
  1422. X    if (flag & nf_NONVOL)
  1423. X        strcat(buf, "nonvol ");
  1424. X    if (flag & nf_PRECIOUS)
  1425. X        strcat(buf, "precious ");
  1426. X    if (flag & nf_PSEUDO)
  1427. X        strcat(buf, "pseudo ");
  1428. X    if (flag & nf_REDUNDANT)
  1429. X        strcat(buf, "redundant ");
  1430. X    if (flag & nf_WHEN)
  1431. X        strcat(buf, "when ");
  1432. X    if (flag & nf_DEPNONVOL)
  1433. X        strcat(buf, "depnonvol ");
  1434. X    if (flag & nf_NODELETE)
  1435. X        strcat(buf, "nodelete ");
  1436. X    if (flag & nf_NEWFILE)
  1437. X        strcat(buf, "newfile ");
  1438. X    if (flag & nf_EXIST)
  1439. X        strcat(buf, "exist ");
  1440. X    if (flag & nf_BUSY)
  1441. X        strcat(buf, "busy ");
  1442. X    if (flag & nf_ERR)
  1443. X        strcat(buf, "err ");
  1444. X    if (flag & nf_TRACED)
  1445. X        strcat(buf, "traced ");
  1446. X    if (flag & nf_WARNED)
  1447. X        strcat(buf, "warned ");
  1448. X    if (flag & nf_ORIG)
  1449. X        strcat(buf, "orig ");
  1450. X
  1451. X    if (strlen(buf) > 1)
  1452. X        buf[strlen(buf)-1] = '\0';
  1453. X
  1454. X    strcat(buf, "]");
  1455. X    return new_name(buf);
  1456. X}
  1457. X
  1458. Xchar *
  1459. Xstr_aflag(flag)
  1460. Xreg    int    flag;
  1461. X{
  1462. X    char        buf[128];
  1463. X
  1464. X    strcpy(buf, "[");
  1465. X    if (flag & af_SILENT)
  1466. X        strcat(buf, "silent ");
  1467. X    if (flag & af_IGNORE)
  1468. X        strcat(buf, "ignore ");
  1469. X    if (flag & af_MINUSN)
  1470. X        strcat(buf, "minusn ");
  1471. X    if (flag & af_SYSTEM)
  1472. X        strcat(buf, "system ");
  1473. X    if (flag & af_SCRIPT)
  1474. X        strcat(buf, "script ");
  1475. X
  1476. X    if (strlen(buf) > 1)
  1477. X        buf[strlen(buf)-1] = '\0';
  1478. X
  1479. X    strcat(buf, "]");
  1480. X    return new_name(buf);
  1481. X}
  1482. X
  1483. Xprint_pat(pat)
  1484. Xreg    Pat    *pat;
  1485. X{
  1486. X    if (pat->p_cmd)
  1487. X        printf("`%s`", pat->p_str);
  1488. X    else
  1489. X        printf("%s", pat->p_str);
  1490. X
  1491. X    printf(str_pflag(pat->p_flag));
  1492. X}
  1493. X
  1494. Xprint_act(act)
  1495. Xreg    Act    *act;
  1496. X{
  1497. X    printf(str_aflag(act->a_flag));
  1498. X    printf("%s", act->a_str);
  1499. X}
  1500. X
  1501. Xprint_test(test)
  1502. Xreg    Test    *test;
  1503. X{
  1504. X    reg    List    *ptr;
  1505. X    reg    char    *pre;
  1506. X    reg    Pat    *pat;
  1507. X
  1508. X    if (test == NULL)
  1509. X    {
  1510. X        printf("null");
  1511. X        return;
  1512. X    }
  1513. X
  1514. X    switch (test->t_kind)
  1515. X    {
  1516. X
  1517. Xwhen t_TRUE:    printf("true");
  1518. Xwhen t_FALSE:    printf("false");
  1519. X
  1520. Xwhen t_AND:    print_test(test->t_left);
  1521. X        printf(" and ");
  1522. X        print_test(test->t_right);
  1523. X
  1524. Xwhen t_OR:    print_test(test->t_left);
  1525. X        printf(" or ");
  1526. X        print_test(test->t_right);
  1527. X
  1528. Xwhen t_NOT:    printf("not ");
  1529. X        print_test(test->t_left);
  1530. X
  1531. Xwhen t_CMD:    printf("cmd `%s`", test->t_cmd);
  1532. X
  1533. Xwhen t_MATCH:    printf("match ");
  1534. X        print_pat(test->t_pat);
  1535. X        printf(" against");
  1536. X        printf(" (");
  1537. X        print_pat((Pat *) first(test->t_list));
  1538. X        printf(") ");
  1539. X        print_pat((Pat *) last(test->t_list));
  1540. X
  1541. Xwhen t_LIST:    printf("list ");
  1542. X        print_pat(test->t_pat);
  1543. X
  1544. X        printf(" in (");
  1545. X        pre = "";
  1546. X        for_list (ptr, test->t_list)
  1547. X        {
  1548. X            pat = (Pat *) ldata(ptr);
  1549. X            printf(pre);
  1550. X            print_pat(pat);
  1551. X            pre = ", ";
  1552. X        }
  1553. X
  1554. X        printf(")");
  1555. X
  1556. Xwhen t_EXIST:    printf("exist ");
  1557. X        print_pat(test->t_pat);
  1558. X
  1559. Xwhen t_CANDO:    printf("cando ");
  1560. X        print_pat(test->t_pat);
  1561. X
  1562. Xwhen t_OK:    printf("ok ");
  1563. X        print_pat(test->t_pat);
  1564. X
  1565. Xotherwise:    printf("Bad type kind %d in print_test\n", test->t_kind);
  1566. X
  1567. X    }
  1568. X}
  1569. X
  1570. Xprint_entry(entry)
  1571. Xreg    Entry    *entry;
  1572. X{
  1573. X    reg    List    *ptr;
  1574. X    reg    Pat    *pat;
  1575. X    reg    Act    *act;
  1576. X    reg    char    *pre;
  1577. X
  1578. X    printf("ENTRY\nnew: ");
  1579. X    pre = "";
  1580. X    for_list (ptr, entry->e_new)
  1581. X    {
  1582. X        pat = (Pat *) ldata(ptr);
  1583. X        printf(pre);
  1584. X        print_pat(pat);
  1585. X        pre = ", ";
  1586. X    }
  1587. X
  1588. X    printf("\nold: ");
  1589. X    pre = "";
  1590. X    for_list (ptr, entry->e_old)
  1591. X    {
  1592. X        pat = (Pat *) ldata(ptr);
  1593. X        printf(pre);
  1594. X        print_pat(pat);
  1595. X        pre = ", ";
  1596. X    }
  1597. X
  1598. X    printf("\nwhen: ");
  1599. X    pre = "";
  1600. X    for_list (ptr, entry->e_when)
  1601. X    {
  1602. X        pat = (Pat *) ldata(ptr);
  1603. X        printf(pre);
  1604. X        print_pat(pat);
  1605. X        pre = ", ";
  1606. X    }
  1607. X
  1608. X    printf("\ntest: ");
  1609. X    print_test(entry->e_cond);
  1610. X
  1611. X    printf("\nactions:\n");
  1612. X    for_list (ptr, entry->e_act)
  1613. X    {
  1614. X        act = (Act *) ldata(ptr);
  1615. X        print_act(act);
  1616. X    }
  1617. X
  1618. X    printf("\n");
  1619. X}
  1620. X
  1621. Xchar *
  1622. Xstr_nkind(nkind)
  1623. Xreg    N_kind    nkind;
  1624. X{
  1625. X    switch (nkind)
  1626. X    {
  1627. Xwhen n_OK:    return "ok";
  1628. Xwhen n_NOWAY:    return "noway";
  1629. Xwhen n_CANDO:    return "cando";
  1630. X    }
  1631. X
  1632. X    return "bizarre";
  1633. X}
  1634. X
  1635. Xprint_time(str, ntime)
  1636. Xreg    char    *str;
  1637. Xtime_t        ntime;
  1638. X{
  1639. X    extern    char    *ctime();
  1640. X
  1641. X    printf("%s time: %d, %s", str, ntime, ctime(&ntime));
  1642. X}
  1643. X
  1644. Xprint_node(node)
  1645. Xreg    Node    *node;
  1646. X{
  1647. X    reg    List    *ptr;
  1648. X    reg    char    *pre;
  1649. X    reg    Node    *bnode;
  1650. X    reg    Act    *act;
  1651. X
  1652. X    printf("\nNODE\n%s: kind %s flag %s\n", node->n_name, 
  1653. X        str_nkind(node->n_kind), str_pflag(node->n_flag));
  1654. X    print_time("real",  node->n_rtime);
  1655. X    print_time("used",  node->n_utime);
  1656. X    print_time("saved", node->n_stime);
  1657. X
  1658. X    printf("new: ");
  1659. X    pre = "";
  1660. X    for_list (ptr, node->n_new)
  1661. X    {
  1662. X        bnode = (Node *) ldata(ptr);
  1663. X        printf(pre);
  1664. X        printf(bnode->n_name);
  1665. X        pre = ", ";
  1666. X    }
  1667. X
  1668. X    printf("\nold: ");
  1669. X    pre = "";
  1670. X    for_list (ptr, node->n_old)
  1671. X    {
  1672. X        bnode = (Node *) ldata(ptr);
  1673. X        printf(pre);
  1674. X        printf(bnode->n_name);
  1675. X        pre = ", ";
  1676. X    }
  1677. X
  1678. X    printf("\naction:\n");
  1679. X    for_list (ptr, node->n_act)
  1680. X    {
  1681. X        act = (Act *) ldata(ptr);
  1682. X        print_act(act);
  1683. X    }
  1684. X
  1685. X    if (node->n_badguys != (List *) NULL)
  1686. X    {
  1687. X        printf("bad guys: ");
  1688. X        pre = "";
  1689. X        for_list (ptr, node->n_badguys)
  1690. X        {
  1691. X            bnode = (Node *) ldata(ptr);
  1692. X            printf(pre);
  1693. X            printf(bnode->n_name);
  1694. X            pre = ", ";
  1695. X        }
  1696. X
  1697. X        printf("\n");
  1698. X    }
  1699. X
  1700. X    if (node->n_msg != NULL)
  1701. X        printf("msg: %s", node->n_msg);
  1702. X
  1703. X    printf("\n");
  1704. X}
  1705. X
  1706. X#endif
  1707. SHAR_EOF
  1708. if test 4954 -ne "`wc -c < 'print.c'`"
  1709. then
  1710.     echo shar: "error transmitting 'print.c'" '(should have been 4954 characters)'
  1711. fi
  1712. fi
  1713. echo shar: "extracting 'proc.c'" '(8939 characters)'
  1714. if test -f 'proc.c'
  1715. then
  1716.     echo shar: "will not over-write existing file 'proc.c'"
  1717. else
  1718. sed 's/^X//' << \SHAR_EOF > 'proc.c'
  1719. X/*
  1720. X**    Cake interface to the other processes.
  1721. X*/
  1722. X
  1723. Xstatic    char
  1724. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/proc.c,v 1.15 87/10/05 20:15:45 zs Exp $";
  1725. X
  1726. X#include    "cake.h"
  1727. X#include    <ctype.h>
  1728. X#include    <errno.h>
  1729. X#include    <signal.h>
  1730. X#include    <fcntl.h>
  1731. X#include    <sys/param.h>
  1732. X
  1733. Xextern    List    *active_procs;        /* of Proc    */
  1734. X
  1735. X/*
  1736. X**    Process the given command in the manner described by the args.
  1737. X*/
  1738. X
  1739. Xint
  1740. Xcake_proc(cmd, type, file, node, func, args)
  1741. Xreg    char    *cmd;
  1742. Xreg    A_kind    type;
  1743. Xreg    char    *file;
  1744. Xreg    Node    *node;
  1745. Xreg    int    (*func)();
  1746. Xreg    List    *args;
  1747. X{
  1748. X    extern    bool    has_meta();
  1749. X    extern    char    *strip_backslash();
  1750. X    extern    char    *shell_path[2];
  1751. X    extern    char    *shell_cmd[2];
  1752. X    extern    char    *shell_opt[2];
  1753. X    char        *argv[MAXARGS];
  1754. X    reg    Proc    *proc;
  1755. X    reg    int    pid;
  1756. X    reg    char    *script_filename;
  1757. X
  1758. X    cmd = strip_backslash(cmd);
  1759. X
  1760. X#ifdef    CAKEDEBUG
  1761. X    if (file != NULL)
  1762. X        cdebug("file is %s\n", file);
  1763. X    else
  1764. X        cdebug("file is NULL\n");
  1765. X#endif
  1766. X
  1767. X    if (type == Exec && has_meta(cmd, TRUE))
  1768. X        type = System;
  1769. X
  1770. X    cdebug("cake_proc, type %d: %s\n", type, cmd);
  1771. X    fflush(stdout);
  1772. X
  1773. X    if (type == Exec)
  1774. X        parse_args(cmd, argv);
  1775. X    or (type == Script)
  1776. X    {
  1777. X        reg    FILE    *script_fp;
  1778. X
  1779. X        script_filename = get_newname();
  1780. X        if ((script_fp = fopen(script_filename, "w")) == NULL)
  1781. X        {
  1782. X            sprintf(scratchbuf, "cake system error, fopen %s", script_filename);
  1783. X            perror(scratchbuf);
  1784. X            exit_cake(FALSE);
  1785. X        }
  1786. X
  1787. X        fprintf(script_fp, "%s", cmd);
  1788. X        fclose(script_fp);
  1789. X    }
  1790. X
  1791. X    mutex_lock();
  1792. X    if ((pid = vfork()) == 0)
  1793. X    {
  1794. X        reg    int    fd;
  1795. X
  1796. X#ifdef    CLOSE_ALL
  1797. X        for (fd = 3; fd < NOFILE; fd++)
  1798. X            close(fd);
  1799. X#endif
  1800. X
  1801. X        if (file != NULL)
  1802. X        {
  1803. X            if (close(1) != 0)
  1804. X            {
  1805. X                perror("cake system error, close stdout");
  1806. X                _exit(127);
  1807. X            }
  1808. X
  1809. X            if ((fd = open(file, O_WRONLY|O_CREAT, 0600)) < 0)
  1810. X            {
  1811. X                perror("cake system error, reopen stdout");
  1812. X                _exit(127);
  1813. X            }
  1814. X
  1815. X            if (fd != 1)
  1816. X            {
  1817. X                fprintf(stderr, "cake system error: reopen stdout gives fd %d\n", fd);
  1818. X                _exit(127);
  1819. X            }
  1820. X        }
  1821. X
  1822. X        switch (type)
  1823. X        {
  1824. X
  1825. X    when Script:    if (shell_opt[1] != NULL)
  1826. X                execl(shell_path[1], shell_cmd[1], shell_opt[1], script_filename, 0);
  1827. X            else
  1828. X                execl(shell_path[1], shell_cmd[1], script_filename, 0);
  1829. X
  1830. X            perror("cake system error, shell script exec");
  1831. X            _exit(127);
  1832. X
  1833. X    when System:    if (shell_opt[0] != NULL)
  1834. X                execl(shell_path[0], shell_cmd[0], shell_opt[0], cmd, 0);
  1835. X            else
  1836. X                execl(shell_path[0], shell_cmd[0], cmd, 0);
  1837. X
  1838. X            perror("cake system error, shell exec");
  1839. X            _exit(127);
  1840. X
  1841. X    when Exec:    execvp(argv[0], argv);
  1842. X            sprintf(scratchbuf, "cake system error, %s exec", argv[0]);
  1843. X            perror(scratchbuf);
  1844. X            _exit(127);
  1845. X
  1846. X    otherwise:    fprintf(stderr, "cake internal error: type = %x in cake_proc\n", type);
  1847. X            _exit(127);
  1848. X        }
  1849. X    }
  1850. X    or (pid == -1)
  1851. X    {
  1852. X        perror("cake system error, fork");
  1853. X        exit_cake(FALSE);
  1854. X    }
  1855. X
  1856. X    proc = make(Proc);
  1857. X    proc->pr_pid  = pid;
  1858. X    proc->pr_node = node;
  1859. X    proc->pr_func = func;
  1860. X    proc->pr_args = args;
  1861. X    proc->pr_run  = TRUE;
  1862. X    addtail(active_procs, proc);
  1863. X    cdebug("cake_proc pid = %d\n", pid);
  1864. X
  1865. X    mutex_unlock();
  1866. X    if (type == Script && ! cakedebug)
  1867. X    {
  1868. X        cdebug("cake_proc unlink script_filename %s\n", script_filename);
  1869. X        if (unlink(script_filename) != 0)
  1870. X        {
  1871. X            sprintf(scratchbuf, "cake system error, unlink %s", script_filename);
  1872. X            perror(scratchbuf);
  1873. X            exit_cake(FALSE);
  1874. X        }
  1875. X    }
  1876. X
  1877. X    return pid;
  1878. X}
  1879. X
  1880. X/*
  1881. X**    The cake code allows many child processes to be running
  1882. X**    at any given time. Cake waits for these processes
  1883. X**    when their results are required. However, there is no
  1884. X**    necessary relationship between between when a process exits
  1885. X**    and when its product is needed.
  1886. X**
  1887. X**    The list of active processes contains all running processes
  1888. X**    and all exited processes that haven't been waited for yet.
  1889. X**    Cake_wait maintains this list. Whenever cake_wait gets
  1890. X**    an exit report from wait, it invokes the function (if any)
  1891. X**    associated with the exited process. If the exited process
  1892. X**    is the one cake_wait is looking for, it returns; otherwise
  1893. X**    it calls wait again and again until it finds that process.
  1894. X*/
  1895. X
  1896. XWait
  1897. Xcake_wait(pid)
  1898. Xreg    int    pid;
  1899. X{
  1900. X    extern    List    *find_process();
  1901. X    reg    int    exitpid;
  1902. X    reg    List    *ptr;
  1903. X    reg    Proc    *proc;
  1904. X    Wait        status;
  1905. X
  1906. X    mutex_lock();
  1907. X    ptr  = find_process(pid);
  1908. X    proc = (Proc *) ldata(ptr);
  1909. X    if (! proc->pr_run)
  1910. X    {
  1911. X        status = proc->pr_stat;
  1912. X        delete(active_procs, ptr);
  1913. X        mutex_unlock();
  1914. X        return status;
  1915. X    }
  1916. X
  1917. X    while ((exitpid = wait(&status)) != -1)
  1918. X    {
  1919. X        mutex_lock();
  1920. X        ptr  = find_process(exitpid);
  1921. X        proc = (Proc *) ldata(ptr);
  1922. X        proc->pr_run  = FALSE;
  1923. X        proc->pr_stat = status;
  1924. X        cdebug("cake_wait pid = %d, status = %d\n", exitpid, status.w_status);
  1925. X        fflush(stdout);
  1926. X
  1927. X        if (proc->pr_func != NULL)
  1928. X        {
  1929. X            cdebug("cake_wait calling function at %x\n", proc->pr_func);
  1930. X            fflush(stdout);
  1931. X            (*proc->pr_func)(status, proc->pr_args);
  1932. X        }
  1933. X
  1934. X        if (exitpid == pid)
  1935. X        {
  1936. X            delete(active_procs, ptr);
  1937. X            mutex_unlock();
  1938. X            return status;    /* normal return */
  1939. X        }
  1940. X
  1941. X        mutex_unlock();
  1942. X    }
  1943. X
  1944. X    fprintf(stderr, "cake internal error: waiting for nonactive process %s\n", pid);
  1945. X    exit_cake(TRUE);
  1946. X    return status;    /* to shut up lint */
  1947. X}
  1948. X
  1949. X/*
  1950. X**    Find an active process in the active process list.
  1951. X*/
  1952. X
  1953. XList *
  1954. Xfind_process(pid)
  1955. Xreg    int    pid;
  1956. X{
  1957. X    reg    List    *ptr;
  1958. X    reg    Proc    *proc;
  1959. X    reg    bool    found;
  1960. X
  1961. X    found = FALSE;
  1962. X    for_list (ptr, active_procs)
  1963. X    {
  1964. X        proc = (Proc *) ldata(ptr);
  1965. X        if (proc->pr_pid == pid)
  1966. X        {
  1967. X            found = TRUE;
  1968. X            break;
  1969. X        }
  1970. X    }
  1971. X
  1972. X    if (! found)
  1973. X    {
  1974. X        fprintf(stderr, "cake internal error: cannot find active process %d\n", pid);
  1975. X        exit_cake(TRUE);
  1976. X    }
  1977. X
  1978. X    return ptr;
  1979. X}
  1980. X
  1981. X/*
  1982. X**    Open a filter the cake way, with an execv instead of an execl.
  1983. X*/
  1984. X
  1985. X#define        READSIDE    0
  1986. X#define        WRITESIDE    1
  1987. X
  1988. Xstatic    int    popen_pid[NOFILE];
  1989. X
  1990. XFILE *
  1991. Xcake_popen(argv, mode)
  1992. Xreg    char    *argv[MAXARGS];
  1993. Xreg    char    *mode;
  1994. X{
  1995. X    int        pdesc[2];
  1996. X    reg    int    parent_end, child_end;
  1997. X    reg    int    replaced, pid;
  1998. X    reg    Proc    *proc;
  1999. X
  2000. X    if (pipe(pdesc) < 0)
  2001. X        return NULL;
  2002. X
  2003. X    if (mode[0] == 'r')
  2004. X    {
  2005. X        parent_end = pdesc[READSIDE];
  2006. X        child_end  = pdesc[WRITESIDE];
  2007. X        replaced   = 1;
  2008. X    }
  2009. X    else
  2010. X    {
  2011. X        parent_end = pdesc[WRITESIDE];
  2012. X        child_end  = pdesc[READSIDE];
  2013. X        replaced   = 0;
  2014. X    }
  2015. X
  2016. X    fflush(stdout);
  2017. X    mutex_lock();
  2018. X    if ((pid = vfork()) == 0)
  2019. X    {
  2020. X        close(parent_end);
  2021. X        close(replaced);
  2022. X        if (dup(child_end) != replaced)
  2023. X            _exit(127);
  2024. X
  2025. X        close(child_end);
  2026. X        execv(argv[0], argv);
  2027. X        sprintf(scratchbuf, "cake system error, %s exec", argv[0]);
  2028. X        perror(scratchbuf);
  2029. X        _exit(127);
  2030. X    }
  2031. X    or (pid == -1)
  2032. X    {
  2033. X        close(parent_end);
  2034. X        close(child_end);
  2035. X        perror("cake system error, fork");
  2036. X        exit_cake(FALSE);
  2037. X    }
  2038. X
  2039. X    proc = make(Proc);
  2040. X    proc->pr_pid  = pid;
  2041. X    proc->pr_func = NULL;
  2042. X    proc->pr_args = NULL;
  2043. X    proc->pr_run  = TRUE;
  2044. X    addtail(active_procs, proc);
  2045. X
  2046. X    close(child_end);
  2047. X    popen_pid[parent_end] = pid;
  2048. X    mutex_unlock();
  2049. X
  2050. X    return fdopen(parent_end, mode);
  2051. X}
  2052. X
  2053. Xint
  2054. Xcake_pclose(fp)
  2055. Xreg    FILE    *fp;
  2056. X{
  2057. X    Wait        code;
  2058. X    reg    int    f;
  2059. X
  2060. X    f = fileno(fp);
  2061. X    fclose(fp);
  2062. X    code = cake_wait(popen_pid[f]);
  2063. X    return code.w_status;
  2064. X}
  2065. X
  2066. X/*
  2067. X**    Parse the given command into argv, argc.
  2068. X*/
  2069. X
  2070. Xint
  2071. Xparse_args(cmd, vector)
  2072. Xreg    char    *cmd;
  2073. Xreg    char    **vector;
  2074. X{
  2075. X    char        buf[MAXARGSIZE];
  2076. X    reg    int    i, count;
  2077. X    reg    char    *s;
  2078. X    reg    bool    instring;
  2079. X
  2080. X    cdebug("parse_args: ");
  2081. X
  2082. X    s = cmd;
  2083. X    for (count = 0; *s != '\0'; count++)
  2084. X    {
  2085. X        while (*s != '\0' && isspace(*s))
  2086. X            s++;
  2087. X
  2088. X        instring = FALSE;
  2089. X        for (i = 0; *s != '\0' && (! isspace(*s) || instring); s++)
  2090. X        {
  2091. X            if (*s == '\\')
  2092. X            {
  2093. X                if (s[1] != '\0')
  2094. X                    buf[i++] = *++s;
  2095. X            }
  2096. X            or (*s == '"')
  2097. X                instring = ! instring;
  2098. X            else
  2099. X                buf[i++] = *s;
  2100. X        }
  2101. X
  2102. X        buf[i] = '\0';
  2103. X        if (i >= MAXARGSIZE)
  2104. X        {
  2105. X            fprintf(stderr, "cake: argument '%s' too long\n", buf);
  2106. X            exit_cake(FALSE);
  2107. X        }
  2108. X
  2109. X        if (count >= MAXARGS)
  2110. X        {
  2111. X            fprintf(stderr, "cake: '%s' has too many arguments\n", cmd);
  2112. X            exit_cake(FALSE);
  2113. X        }
  2114. X
  2115. X        if (i == 0)
  2116. X            count--;
  2117. X        else
  2118. X        {
  2119. X            cdebug("<%s>", buf);
  2120. X            vector[count] = new_name(buf);
  2121. X        }
  2122. X    }
  2123. X
  2124. X    vector[count] = NULL;
  2125. X    cdebug("/%d\n", count);
  2126. X    return count;
  2127. X}
  2128. X
  2129. X/*
  2130. X**    Strip one level of backslashes from the given string.
  2131. X*/
  2132. X
  2133. Xchar *
  2134. Xstrip_backslash(str)
  2135. Xreg    char    *str;
  2136. X{
  2137. X    char        buf[MAXSIZE];
  2138. X    reg    char    *s;
  2139. X    reg    int    i;
  2140. X
  2141. X    if (index(str, '\\') == NULL)
  2142. X        return str;
  2143. X
  2144. X    for (i = 0, s = str; *s != '\0'; s++)
  2145. X    {
  2146. X        if (*s != '\\')
  2147. X            buf[i++] = *s;
  2148. X        or (s[1] != '\0')
  2149. X            buf[i++] = *++s;
  2150. X    }
  2151. X
  2152. X    buf[i] = '\0';
  2153. X    if (i >= MAXSIZE)
  2154. X    {
  2155. X        fprintf(stderr, "cake: command '%s' too long.\n", str);
  2156. X        exit_cake(FALSE);
  2157. X    }
  2158. X
  2159. X    return new_name(buf);
  2160. X}
  2161. X
  2162. X/*
  2163. X**    These functions implement mutual exclusion.
  2164. X**    They prevent cake from being interrupted
  2165. X**    between calls to lock and unlock.
  2166. X**    This is used to preserve the consistency
  2167. X**    of the active_procs data structure in the presence
  2168. X**    of multiple executing children.
  2169. X*/
  2170. X
  2171. X#if 0        /* mutual exclusion is not necessary & has bug */
  2172. X#ifdef    ATT
  2173. Xint    (*signalint)();
  2174. Xint    (*signalquit)();
  2175. X#else
  2176. Xint    signalmask;
  2177. X#endif
  2178. X#endif
  2179. X
  2180. Xmutex_lock()
  2181. X{
  2182. X#if 0
  2183. X#ifdef    ATT
  2184. X    signalint  = signal(SIGINT,  SIG_IGN);
  2185. X    signalquit = signal(SIGQUIT, SIG_IGN);
  2186. X#else
  2187. X    signalmask = sigblock(mask(SIGINT)|mask(SIGQUIT));
  2188. X#endif
  2189. X#endif
  2190. X}
  2191. X
  2192. Xmutex_unlock()
  2193. X{
  2194. X#if 0
  2195. X#ifdef    ATT
  2196. X    signal(SIGINT,  signalint);
  2197. X    signal(SIGQUIT, signalquit);
  2198. X#else
  2199. X    sigsetmask(signalmask);
  2200. X#endif
  2201. X#endif
  2202. X}
  2203. SHAR_EOF
  2204. if test 8939 -ne "`wc -c < 'proc.c'`"
  2205. then
  2206.     echo shar: "error transmitting 'proc.c'" '(should have been 8939 characters)'
  2207. fi
  2208. fi
  2209. echo shar: "extracting 'sym.c'" '(4553 characters)'
  2210. if test -f 'sym.c'
  2211. then
  2212.     echo shar: "will not over-write existing file 'sym.c'"
  2213. else
  2214. sed 's/^X//' << \SHAR_EOF > 'sym.c'
  2215. X/*
  2216. X**    Symbol table module
  2217. X*/
  2218. X
  2219. Xstatic    char
  2220. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/sym.c,v 1.15 87/10/05 20:16:08 zs Exp $";
  2221. X
  2222. X#include    "cake.h"
  2223. X
  2224. Xtypedef    struct    s_out
  2225. X{
  2226. X    char    *o_cmd;
  2227. X    char    *o_out;
  2228. X} Out;
  2229. X
  2230. Xtypedef    struct    s_stat
  2231. X{
  2232. X    char    *s_cmd;
  2233. X    int    s_stat;
  2234. X} Stat;
  2235. X
  2236. Xextern    int    hash();
  2237. Xextern    Cast    name_key();    extern    bool    name_equal();
  2238. Xextern    Cast    node_key();    extern    bool    node_equal();
  2239. Xextern    Cast    out_key();    extern    bool    out_equal();
  2240. Xextern    Cast    stat_key();    extern    bool    stat_equal();
  2241. XTable    name_tab = { SIZE, NULL, name_key, hash, name_equal };
  2242. XTable    node_tab = { SIZE, NULL, node_key, hash, node_equal };
  2243. XTable    out_tab  = { SIZE, NULL, out_key,  hash, out_equal  };
  2244. XTable    stat_tab = { SIZE, NULL, stat_key, hash, stat_equal };
  2245. X
  2246. X/*
  2247. X**    Initialize the name and the command tables.
  2248. X*/
  2249. X
  2250. Xinit_sym()
  2251. X{
  2252. X    init_table(name_tab);
  2253. X    init_table(node_tab);
  2254. X    init_table(out_tab);
  2255. X    init_table(stat_tab);
  2256. X}
  2257. X
  2258. X/**********************************************************************/
  2259. X/*    Name table                              */
  2260. X
  2261. X/*
  2262. X**    Save the given string in the name table if not already there;
  2263. X**    return its new address. This address is unique, so comparing
  2264. X**    two identifiers for equality can be done by comparing their
  2265. X**    addresses.
  2266. X*/
  2267. X
  2268. Xchar *
  2269. Xnew_name(str)
  2270. Xreg    char    *str;
  2271. X{
  2272. X    reg    Cast    old;
  2273. X    reg    char    *copy;
  2274. X
  2275. X    if ((old = lookup_table(name_tab, str)) != NULL)
  2276. X        return (char *) old;
  2277. X
  2278. X    copy = (char *) newmem(strlen(str) + 1);
  2279. X    strcpy(copy, str);
  2280. X    insert_table(name_tab, copy);
  2281. X
  2282. X    return copy;
  2283. X}
  2284. X
  2285. XCast
  2286. Xname_key(entry)
  2287. Xreg    Cast    entry;
  2288. X{
  2289. X    return entry;
  2290. X}
  2291. X
  2292. Xbool
  2293. Xname_equal(key1, key2)
  2294. Xreg    Cast    key1, key2;
  2295. X{
  2296. X    return streq((char *) key1, (char *) key2);
  2297. X}
  2298. X
  2299. X/**********************************************************************/
  2300. X/*    Node table                              */
  2301. X
  2302. X/*
  2303. X**    Th insertion function for the node table is chase(),
  2304. X**    which is in chase.c with the rest of the chase stuff.
  2305. X*/
  2306. X
  2307. X/*
  2308. X**    This function merely reports on the results
  2309. X**    of past calls to chase.
  2310. X*/
  2311. X
  2312. XNode *
  2313. Xchase_node(name)
  2314. Xreg    char    *name;
  2315. X{
  2316. X    return (Node *) lookup_table(node_tab, name);
  2317. X}
  2318. X
  2319. X/*
  2320. X**    Return a list of all the nodes of this run.
  2321. X*/
  2322. X
  2323. XList *
  2324. Xget_allnodes()
  2325. X{
  2326. X    return contents_table(node_tab);
  2327. X}
  2328. X
  2329. XCast
  2330. Xnode_key(entry)
  2331. Xreg    Cast    entry;
  2332. X{
  2333. X    return (Cast) ((Node *) entry)->n_name;
  2334. X}
  2335. X
  2336. Xbool
  2337. Xnode_equal(key1, key2)
  2338. Xreg    Cast    key1, key2;
  2339. X{
  2340. X#ifdef    EXTRACHECK
  2341. X    if (key1 != key2 && streq((char *) key1, (char *) key2))
  2342. X    {
  2343. X        fprintf(stderr, "cake internal error: inconsistency in node_equal\n");
  2344. X        exit_cake(TRUE);
  2345. X    }
  2346. X#endif
  2347. X
  2348. X    return key1 == key2;
  2349. X}
  2350. X
  2351. X/**********************************************************************/
  2352. X/*    Command output table                          */
  2353. X
  2354. X#ifdef    STATS_FILE
  2355. Xint    out_tried = 0;
  2356. Xint    out_found = 0;
  2357. X#endif
  2358. X
  2359. X/*
  2360. X**    Save a command and its output.
  2361. X*/
  2362. X
  2363. Xnew_out(cmd, output)
  2364. Xreg    char    *cmd;
  2365. Xreg    char    *output;
  2366. X{
  2367. X    reg    Out    *out;
  2368. X
  2369. X    out = make(Out);
  2370. X    out->o_cmd = cmd;
  2371. X    out->o_out = output;
  2372. X    insert_table(out_tab, out);
  2373. X}
  2374. X
  2375. X/*
  2376. X**    Return the output if any associated with a given command.
  2377. X*/
  2378. X
  2379. Xchar *
  2380. Xget_out(cmd)
  2381. Xreg    char    *cmd;
  2382. X{
  2383. X    reg    Out    *out;
  2384. X
  2385. X#ifdef    STATS_FILE
  2386. X    out_tried++;
  2387. X#endif
  2388. X
  2389. X    if ((out = (Out *) lookup_table(out_tab, cmd)) == NULL)
  2390. X        return NULL;
  2391. X
  2392. X#ifdef    STATS_FILE
  2393. X    out_found++;
  2394. X#endif
  2395. X
  2396. X    return out->o_out;
  2397. X}
  2398. X
  2399. XCast
  2400. Xout_key(entry)
  2401. Xreg    Cast    entry;
  2402. X{
  2403. X    return (Cast) ((Out *) entry)->o_cmd;
  2404. X}
  2405. X
  2406. Xbool
  2407. Xout_equal(key1, key2)
  2408. Xreg    Cast    key1, key2;
  2409. X{
  2410. X#ifdef    EXTRACHECK
  2411. X    if (key1 != key2 && streq((char *) key1, (char *) key2))
  2412. X    {
  2413. X        fprintf(stderr, "cake internal error: inconsistency in out_equal\n");
  2414. X        exit_cake(TRUE);
  2415. X    }
  2416. X#endif
  2417. X
  2418. X    return key1 == key2;
  2419. X}
  2420. X
  2421. X/**********************************************************************/
  2422. X/*    Command status table                          */
  2423. X
  2424. X#ifdef    STATS_FILE
  2425. Xint    stat_tried = 0;
  2426. Xint    stat_found = 0;
  2427. X#endif
  2428. X
  2429. X/*
  2430. X**    Save a command and its status.
  2431. X*/
  2432. X
  2433. Xnew_stat(cmd, status)
  2434. Xreg    char    *cmd;
  2435. Xreg    int    status;
  2436. X{
  2437. X    reg    Stat    *stat;
  2438. X
  2439. X    stat = make(Stat);
  2440. X    stat->s_cmd  = cmd;
  2441. X    stat->s_stat = status;
  2442. X    insert_table(stat_tab, stat);
  2443. X}
  2444. X
  2445. X/*
  2446. X**    Return the status if any associated with a given command.
  2447. X*/
  2448. X
  2449. Xbool
  2450. Xget_stat(cmd, code)
  2451. Xreg    char    *cmd;
  2452. Xreg    int    *code;
  2453. X{
  2454. X    reg    Stat    *stat;
  2455. X
  2456. X#ifdef    STATS_FILE
  2457. X    stat_tried++;
  2458. X#endif
  2459. X
  2460. X    if ((stat = (Stat *) lookup_table(stat_tab, cmd)) == NULL)
  2461. X        return FALSE;
  2462. X
  2463. X#ifdef    STATS_FILE
  2464. X    stat_found++;
  2465. X#endif
  2466. X
  2467. X    *code = stat->s_stat;
  2468. X    return TRUE;
  2469. X}
  2470. X
  2471. XCast
  2472. Xstat_key(entry)
  2473. Xreg    Cast    entry;
  2474. X{
  2475. X    return (Cast) ((Stat *) entry)->s_cmd;
  2476. X}
  2477. X
  2478. Xbool
  2479. Xstat_equal(key1, key2)
  2480. Xreg    Cast    key1, key2;
  2481. X{
  2482. X#ifdef    EXTRACHECK
  2483. X    if (key1 != key2 && streq((char *) key1, (char *) key2))
  2484. X    {
  2485. X        fprintf(stderr, "cake internal error: inconsistency in stat_equal\n");
  2486. X        exit_cake(TRUE);
  2487. X    }
  2488. X#endif
  2489. X
  2490. X    return key1 == key2;
  2491. X}
  2492. SHAR_EOF
  2493. if test 4553 -ne "`wc -c < 'sym.c'`"
  2494. then
  2495.     echo shar: "error transmitting 'sym.c'" '(should have been 4553 characters)'
  2496. fi
  2497. fi
  2498. echo shar: "extracting 'sys.c'" '(2672 characters)'
  2499. if test -f 'sys.c'
  2500. then
  2501.     echo shar: "will not over-write existing file 'sys.c'"
  2502. else
  2503. sed 's/^X//' << \SHAR_EOF > 'sys.c'
  2504. X/*
  2505. X**    Cake system interface.
  2506. X*/
  2507. X
  2508. Xstatic    char
  2509. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/sys.c,v 1.15 87/10/05 20:16:20 zs Exp $";
  2510. X
  2511. X#include    "cake.h"
  2512. X
  2513. X/*
  2514. X**    Change to the directory of the cakefile.
  2515. X**    Return the shortened name of the cakefile.
  2516. X*/
  2517. X
  2518. Xchar *
  2519. Xdir_setup(name)
  2520. Xreg    char    *name;
  2521. X{
  2522. X    char        buf[MAXSIZE];
  2523. X    reg    int    i, l;    /* l is the subscript of the last / */
  2524. X
  2525. X    l = -1;
  2526. X    for (i = 0; name[i] != '\0'; i++)
  2527. X        if (name[i] == '/')
  2528. X            l = i;
  2529. X
  2530. X    if (l < 0)
  2531. X        return name;
  2532. X    else
  2533. X    {
  2534. X        for (i = 0; i < l; i++)
  2535. X            buf[i] = name[i];
  2536. X        
  2537. X        if (i == 0)
  2538. X            buf[i++] = '/';
  2539. X
  2540. X        buf[i] = '\0';
  2541. X        if (chdir(buf) != 0)
  2542. X        {
  2543. X            sprintf(scratchbuf, "cake system error, chdir %s", buf);
  2544. X            perror(scratchbuf);
  2545. X            exit(1);
  2546. X        }
  2547. X
  2548. X        return name+l+1;
  2549. X    }
  2550. X}
  2551. X
  2552. X/*
  2553. X**    Set up the arguments to shell exec's.
  2554. X**    pattern: execl("/bin/sh", "sh", "-c", s, 0);
  2555. X**    pattern: execl("/bin/csh", "csh", "-cf", s, 0);
  2556. X*/
  2557. X
  2558. Xchar    *shell_path[2];
  2559. Xchar    *shell_cmd[2];
  2560. Xchar    *shell_opt[2];
  2561. X
  2562. Xshell_setup(shell, which)
  2563. Xreg    char    *shell;
  2564. Xreg    int    which;
  2565. X{
  2566. X    char        buf[MAXSIZE];
  2567. X    reg    char    *s;
  2568. X    reg    int    i, l;
  2569. X
  2570. X    /* find the shell path */
  2571. X    i = 0;
  2572. X    for (s = shell; *s != '\0' && *s != ' ' && *s != '\t'; s++)
  2573. X        buf[i++] = *s;
  2574. X    
  2575. X    buf[i] = '\0';
  2576. X    shell_path[which] = new_name(buf);
  2577. X
  2578. X    for (; *s != '\0' && *s != '-'; s++)
  2579. X        ;
  2580. X
  2581. X    /* find the options */
  2582. X    i = 0;
  2583. X    for (; *s != '\0' && *s != ' ' && *s != '\t'; s++)
  2584. X        buf[i++] = *s;
  2585. X    
  2586. X    buf[i] = '\0';
  2587. X    if (i != 0)
  2588. X        shell_opt[which] = new_name(buf);
  2589. X    else
  2590. X        shell_opt[which] = NULL;
  2591. X
  2592. X    if (*s != NULL)
  2593. X    {
  2594. X        fprintf(stderr, "cake: cannot parse shell command '%s'\n", shell);
  2595. X        exit_cake(FALSE);
  2596. X    }
  2597. X
  2598. X    /* find the shell command itself */
  2599. X    s = shell_path[which];
  2600. X    l = -1;
  2601. X    for (i = 0; s[i] != '\0'; i++)
  2602. X        if (s[i] == '/')
  2603. X            l = i;
  2604. X
  2605. X    shell_cmd[which] = new_name(s+l+1);
  2606. X
  2607. X    if (cakedebug)
  2608. X    {
  2609. X        printf("shell path%d: %s\n", which, shell_path[which]);
  2610. X        printf("shell cmd%d:  %s\n", which, shell_cmd[which]);
  2611. X        if (shell_opt[which] != NULL)
  2612. X            printf("shell opt%d:  %s\n", which, shell_opt[which]);
  2613. X        else
  2614. X            printf("shell opt%d:  NULL\n", which);
  2615. X    }
  2616. X}
  2617. X
  2618. Xbool    metatab[CHARSETSIZE];
  2619. X
  2620. X/*
  2621. X**    Set up the metacharacter table.
  2622. X*/
  2623. X
  2624. Xmeta_setup(metachars)
  2625. Xreg    char    *metachars;
  2626. X{
  2627. X    reg    int    i;
  2628. X    reg    char    *s;
  2629. X
  2630. X    for (i = 0; i < CHARSETSIZE; i++)
  2631. X        metatab[i] = FALSE;
  2632. X    
  2633. X    for (s = metachars; *s != '\0'; s++)
  2634. X        metatab[*s] = TRUE;
  2635. X}
  2636. X
  2637. X/*
  2638. X**    Decide whether the given string has metacharacters or not.
  2639. X**    The second arg tells whether to honour backslash escapes.
  2640. X*/
  2641. X
  2642. Xbool
  2643. Xhas_meta(str, allow_esc)
  2644. Xreg    char    *str;
  2645. Xreg    bool    allow_esc;
  2646. X{
  2647. X    reg    char    *s;
  2648. X
  2649. X    for (s = str; *s != '\0'; s++)
  2650. X        if (metatab[(unsigned) *s])
  2651. X            return TRUE;
  2652. X        or (allow_esc && (*s == '\\'))
  2653. X        {
  2654. X            if (s[1] != '\0')
  2655. X                s++;
  2656. X        }
  2657. X    
  2658. X    return FALSE;
  2659. X}
  2660. SHAR_EOF
  2661. if test 2672 -ne "`wc -c < 'sys.c'`"
  2662. then
  2663.     echo shar: "error transmitting 'sys.c'" '(should have been 2672 characters)'
  2664. fi
  2665. fi
  2666. echo shar: "extracting 'table.c'" '(2269 characters)'
  2667. if test -f 'table.c'
  2668. then
  2669.     echo shar: "will not over-write existing file 'table.c'"
  2670. else
  2671. sed 's/^X//' << \SHAR_EOF > 'table.c'
  2672. X/*
  2673. X**    Table handling module.
  2674. X**
  2675. X**    This file supplies data manipulation routines to other modules;
  2676. X**    it does not store any data itself. Its routines are generic,
  2677. X**    applicable to the storage of any kind of data structure with
  2678. X**    primary key and a hash function on it.
  2679. X*/
  2680. X
  2681. Xstatic    char
  2682. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/table.c,v 1.15 87/10/05 20:16:28 zs Exp $";
  2683. X
  2684. X#include    "cake.h"
  2685. X
  2686. X/*
  2687. X**    Initialize a table.
  2688. X*/
  2689. X
  2690. X_init_table(table)
  2691. Xreg    Table    *table;
  2692. X{
  2693. X    reg    int    i;
  2694. X
  2695. X    table->ta_store = make_many(List *, table->ta_size);
  2696. X    for (i = 0; i < table->ta_size; i++)
  2697. X        table->ta_store[i] = NULL;
  2698. X}
  2699. X
  2700. X/*
  2701. X**    Look up and return the entry corresponding to the key
  2702. X**    in a table.
  2703. X*/
  2704. X
  2705. XCast
  2706. X_lookup_table(table, key)
  2707. Xreg    Table    *table;
  2708. Xreg    Cast    key;
  2709. X{
  2710. X    reg    List    *ptr;
  2711. X    reg    int    h;
  2712. X
  2713. X    put_trail("lookup_table", "start");
  2714. X    h = tablehash(table)(key);
  2715. X    for_list (ptr, table->ta_store[h])
  2716. X    {
  2717. X        if (tableequal(table)(key, tablekey(table)(ldata(ptr))))
  2718. X        {
  2719. X#ifdef    EXTRACHECK
  2720. X            if (ldata(ptr) == NULL)
  2721. X            {
  2722. X                fprintf(stderr, "cake internal error: returning null in lookup_table\n");
  2723. X                exit_cake(TRUE);
  2724. X            }
  2725. X#endif
  2726. X            put_trail("lookup_table", "finish");
  2727. X            return ldata(ptr);
  2728. X        }
  2729. X    }
  2730. X
  2731. X    put_trail("lookup_table", "finish");
  2732. X    return NULL;
  2733. X}
  2734. X
  2735. X/*
  2736. X**    Insert a new entry into the table.
  2737. X**    Return whether it was there before.
  2738. X*/
  2739. X
  2740. Xbool
  2741. X_insert_table(table, entry)
  2742. Xreg    Table    *table;
  2743. Xreg    Cast    entry;
  2744. X{
  2745. X    reg    List    *ptr;
  2746. X    reg    Cast    key;
  2747. X    reg    int    h;
  2748. X
  2749. X    put_trail("insert_table", "start");
  2750. X    key = tablekey(table)(entry);
  2751. X    h   = tablehash(table)(key);
  2752. X    for_list (ptr, table->ta_store[h])
  2753. X        if (tableequal(table)(key, tablekey(table)(ldata(ptr))))
  2754. X        {
  2755. X            put_trail("insert_table", "finish");
  2756. X            return TRUE;
  2757. X        }
  2758. X
  2759. X    table->ta_store[h] = addhead(table->ta_store[h], entry);
  2760. X    put_trail("insert_table", "finish");
  2761. X    return FALSE;
  2762. X}
  2763. X
  2764. X/*
  2765. X**    Hash str into the range 0 to SIZE-1.
  2766. X*/
  2767. X
  2768. Xint
  2769. Xhash(s)
  2770. Xreg    char    *s;
  2771. X{
  2772. X    reg    int    h;
  2773. X
  2774. X    for (h = 0; *s != '\0'; s++)
  2775. X        h = (h << 1) + *s;
  2776. X
  2777. X    return (h >= 0? h: -h) % SIZE;
  2778. X}
  2779. X
  2780. X/*
  2781. X**    Return a list of all the entries in a table.
  2782. X*/
  2783. X
  2784. XList *
  2785. X_contents_table(table)
  2786. Xreg    Table    *table;
  2787. X{
  2788. X    reg    List    *all;
  2789. X    reg    List    *ptr;
  2790. X    reg    int    i;
  2791. X
  2792. X    all = makelist0();
  2793. X    for (i = 0; i < table->ta_size; i++)
  2794. X        for_list (ptr, table->ta_store[i])
  2795. X            addtail(all, ldata(ptr));    /* na */
  2796. X
  2797. X    return all;
  2798. X}
  2799. SHAR_EOF
  2800. if test 2269 -ne "`wc -c < 'table.c'`"
  2801. then
  2802.     echo shar: "error transmitting 'table.c'" '(should have been 2269 characters)'
  2803. fi
  2804. fi
  2805. echo shar: "extracting 'test.c'" '(3874 characters)'
  2806. if test -f 'test.c'
  2807. then
  2808.     echo shar: "will not over-write existing file 'test.c'"
  2809. else
  2810. sed 's/^X//' << \SHAR_EOF > 'test.c'
  2811. X/*
  2812. X**    Module to handle Cake's tests.
  2813. X*/
  2814. X
  2815. Xstatic    char
  2816. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/test.c,v 1.15 87/10/05 20:16:34 zs Exp $";
  2817. X
  2818. X#include    "cake.h"
  2819. X
  2820. Xbool
  2821. Xeval(node, test, env)
  2822. Xreg    Node    *node;
  2823. Xreg    Test    *test;
  2824. XEnv        env;
  2825. X{
  2826. X    extern    char    *expand_cmds();
  2827. X    extern    int    cake_proc();
  2828. X    extern    Wait    cake_wait();
  2829. X    extern    Node    *chase();
  2830. X    extern    bool    get_stat();
  2831. X    extern    bool    exist();
  2832. X    extern    char    *ground();
  2833. X    char        buf[256];
  2834. X    Wait        status;
  2835. X    reg    List    *ptr;
  2836. X    reg    Pat    *pat;
  2837. X    reg    char    *text1, *text2;
  2838. X    reg    char    *cmd;
  2839. X    reg    Node    *chasenode;
  2840. X    reg    int    result;
  2841. X    reg    int    pid;
  2842. X
  2843. X    if (test == (Test *) NULL)
  2844. X        return TRUE;
  2845. X
  2846. X#ifdef    CAKEDEBUG
  2847. X    if (cakedebug)
  2848. X    {
  2849. X        printf("testing ");
  2850. X        print_test(test);
  2851. X        printf("\n");
  2852. X    }
  2853. X#endif
  2854. X
  2855. X    switch (test->t_kind)
  2856. X    {
  2857. X
  2858. Xwhen t_TRUE:    return TRUE;
  2859. Xwhen t_FALSE:    return FALSE;
  2860. Xwhen t_AND:    return eval(node, test->t_left, env) && eval(node, test->t_right, env);
  2861. Xwhen t_OR:    return eval(node, test->t_left, env) || eval(node, test->t_right, env);
  2862. Xwhen t_NOT:    return ! eval(node, test->t_left, env);
  2863. X
  2864. Xwhen t_CMD:    if (get_stat(test->t_cmd, &status.w_status))
  2865. X        {
  2866. X            test->t_kind = (status.w_status == 0)? t_TRUE: t_FALSE;
  2867. X            cdebug("test cmd cache %s: %s\n", test->t_cmd,
  2868. X                (status.w_status == 0)? "True": "False");
  2869. X            return (status.w_status == 0)? TRUE: FALSE;
  2870. X        }
  2871. X
  2872. X        cmd = expand_cmds(ground(env, test->t_cmd));
  2873. X        pid = cake_proc(cmd, Exec, "/dev/null", (Node *) NULL,
  2874. X            (int (*)()) NULL, (List *) NULL);
  2875. X        status = cake_wait(pid);
  2876. X        new_stat(test->t_cmd, status.w_status);
  2877. X        test->t_kind = (status.w_status == 0)? t_TRUE: t_FALSE;
  2878. X        cdebug("test cmd %s: %s\n", test->t_cmd,
  2879. X            (status.w_status == 0)? "True": "False");
  2880. X        return (status.w_status == 0)? TRUE: FALSE;
  2881. X
  2882. Xwhen t_MATCH:    text1 = (char *) first(test->t_list);    /* -vX    */
  2883. X        text2 = (char *) last(test->t_list);    /* file    */
  2884. X        /* e.g.    sub -vX X.c NULL file.c */
  2885. X        sprintf(buf, "sub %s %s NULL %s > /dev/null",
  2886. X            text1, text2, test->t_pat->p_str);
  2887. X
  2888. X        cmd = new_name(buf);
  2889. X        cdebug("matching command: %s\n", cmd);
  2890. X        if (get_stat(cmd, &status.w_status))
  2891. X        {
  2892. X            test->t_kind = (status.w_status == 0)? t_TRUE: t_FALSE;
  2893. X            cdebug("test cmd cache %s: %s\n", test->t_cmd,
  2894. X                (status.w_status == 0)? "True": "False");
  2895. X            return (status.w_status == 0)? TRUE: FALSE;
  2896. X        }
  2897. X
  2898. X        pid = cake_proc(cmd, Exec, "/dev/null", (Node *) NULL,
  2899. X            (int (*)()) NULL, (List *) NULL);
  2900. X        status = cake_wait(pid);
  2901. X        new_stat(test->t_cmd, status.w_status);
  2902. X        test->t_kind = (status.w_status == 0)? t_TRUE: t_FALSE;
  2903. X        cdebug("test cmd %s: %s\n", test->t_cmd,
  2904. X            (status.w_status == 0)? "True": "False");
  2905. X        return (status.w_status == 0)? TRUE: FALSE;
  2906. X
  2907. Xwhen t_LIST:    for_list (ptr, test->t_list)
  2908. X        {
  2909. X            pat = (Pat *) ldata(ptr);
  2910. X            if (streq(test->t_pat->p_str, pat->p_str))
  2911. X                return TRUE;
  2912. X        }
  2913. X
  2914. X        return FALSE;
  2915. X
  2916. Xwhen t_EXIST:    result = exist(test->t_pat->p_str);
  2917. X        cdebug("test exist %s: %s\n", test->t_pat->p_str,
  2918. X            result? "True": "False");
  2919. X        return result;
  2920. X
  2921. Xwhen t_CANDO:    chasenode = chase(test->t_pat->p_str, 0, (Entry *) NULL);
  2922. X        if (on_node(chasenode, nf_ERR))
  2923. X        {
  2924. X            sprintf(scratchbuf, "cannot evaluate 'cando %s' test for %s",
  2925. X                chasenode->n_name, node->n_name);
  2926. X            add_error(node, new_name(scratchbuf), LNULL, TRUE);
  2927. X        }
  2928. X
  2929. X        result = is_ok(chasenode) || is_cando(chasenode);
  2930. X        cdebug("test cando %s: %s\n", test->t_pat->p_str,
  2931. X            result? "True": "False");
  2932. X        return result;
  2933. X
  2934. Xwhen t_OK:    chasenode = chase(test->t_pat->p_str, 0, (Entry *) NULL);
  2935. X        if (on_node(chasenode, nf_ERR))
  2936. X        {
  2937. X            sprintf(scratchbuf, "cannot evaluate 'ok %s' test for %s",
  2938. X                chasenode->n_name, node->n_name);
  2939. X            add_error(node, new_name(scratchbuf), LNULL, TRUE);
  2940. X        }
  2941. X
  2942. X        result = is_ok(chasenode);
  2943. X        cdebug("test ok %s: %s\n", test->t_pat->p_str,
  2944. X            result? "True": "False");
  2945. X        return result;
  2946. X
  2947. Xotherwise:    fprintf(stderr, "cake internal error: invalid test type %x in eval\n",
  2948. X            test->t_kind);
  2949. X        exit_cake(TRUE);
  2950. X    }
  2951. X
  2952. X    /*NOTREACHED*/
  2953. X    return FALSE;
  2954. X}
  2955. SHAR_EOF
  2956. if test 3874 -ne "`wc -c < 'test.c'`"
  2957. then
  2958.     echo shar: "error transmitting 'test.c'" '(should have been 3874 characters)'
  2959. fi
  2960. fi
  2961. echo shar: "extracting 'trail.c'" '(1045 characters)'
  2962. if test -f 'trail.c'
  2963. then
  2964.     echo shar: "will not over-write existing file 'trail.c'"
  2965. else
  2966. sed 's/^X//' << \SHAR_EOF > 'trail.c'
  2967. X/*
  2968. X**    Trail module.
  2969. X*/
  2970. X
  2971. Xstatic    char
  2972. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/trail.c,v 1.14 86/07/19 12:24:19 zs Exp $";
  2973. X
  2974. X#ifdef    CAKEDEBUG
  2975. X#include    "cake.h"
  2976. X
  2977. X#define        TRAILSIZE    100
  2978. X
  2979. Xstatic    int    trail_entries = 0;    /* no. of calls to put_tr */
  2980. Xstatic    int    slot = 0;        /* next slot          */
  2981. Xstatic    char    *trailfunc[TRAILSIZE];    /* functions and events      */
  2982. Xstatic    char    *trailevent[TRAILSIZE];    /* init to NULL by C      */
  2983. X
  2984. X/*
  2985. X**    Register this function on the trail.
  2986. X*/
  2987. X
  2988. Xput_trail(func, event)
  2989. Xreg    char    *func;
  2990. Xreg    char    *event;
  2991. X{
  2992. X    trailfunc[slot]  = func;
  2993. X    trailevent[slot] = event;
  2994. X
  2995. X    trail_entries++;
  2996. X    if (++slot == TRAILSIZE)
  2997. X        slot = 0;
  2998. X}
  2999. X
  3000. X/*
  3001. X**    Print the trail on the given file.
  3002. X*/
  3003. X
  3004. Xget_trail(fp)
  3005. Xreg    FILE    *fp;
  3006. X{
  3007. X    reg    int    maxent;
  3008. X
  3009. X    fprintf(fp, "^^^^^^^^^^^^^^^^^^^ TRAIL ^^^^^^^^^^^^^^^^^^^\n");
  3010. X    fprintf(fp, "%d entries\n", trail_entries);
  3011. X
  3012. X    maxent = (trail_entries < TRAILSIZE)? trail_entries: TRAILSIZE;
  3013. X    while (maxent-- > 0)
  3014. X    {
  3015. X        if (--slot == -1)
  3016. X            slot = TRAILSIZE - 1;
  3017. X
  3018. X        fprintf(fp, "%s %s\n", trailfunc[slot], trailevent[slot]);
  3019. X    }
  3020. X}
  3021. X#endif
  3022. SHAR_EOF
  3023. if test 1045 -ne "`wc -c < 'trail.c'`"
  3024. then
  3025.     echo shar: "error transmitting 'trail.c'" '(should have been 1045 characters)'
  3026. fi
  3027. fi
  3028. exit 0
  3029. #    End of shell archive
  3030.